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 "input_method_system_ability.h"
1722736c2fSopenharmony_ci
1822736c2fSopenharmony_ci#include <unistd.h>
1922736c2fSopenharmony_ci
2022736c2fSopenharmony_ci#include "ability_manager_client.h"
2122736c2fSopenharmony_ci#include "application_info.h"
2222736c2fSopenharmony_ci#include "combination_key.h"
2322736c2fSopenharmony_ci#include "common_event_support.h"
2422736c2fSopenharmony_ci#include "errors.h"
2522736c2fSopenharmony_ci#include "full_ime_info_manager.h"
2622736c2fSopenharmony_ci#include "global.h"
2722736c2fSopenharmony_ci#include "im_common_event_manager.h"
2822736c2fSopenharmony_ci#include "ime_cfg_manager.h"
2922736c2fSopenharmony_ci#include "ime_info_inquirer.h"
3022736c2fSopenharmony_ci#include "input_client_info.h"
3122736c2fSopenharmony_ci#include "input_method_utils.h"
3222736c2fSopenharmony_ci#include "input_type_manager.h"
3322736c2fSopenharmony_ci#include "ipc_skeleton.h"
3422736c2fSopenharmony_ci#include "iservice_registry.h"
3522736c2fSopenharmony_ci#include "itypes_util.h"
3622736c2fSopenharmony_ci#include "key_event.h"
3722736c2fSopenharmony_ci#include "mem_mgr_client.h"
3822736c2fSopenharmony_ci#include "message_handler.h"
3922736c2fSopenharmony_ci#include "native_token_info.h"
4022736c2fSopenharmony_ci#include "os_account_adapter.h"
4122736c2fSopenharmony_ci#include "scene_board_judgement.h"
4222736c2fSopenharmony_ci#include "system_ability_definition.h"
4322736c2fSopenharmony_ci#ifdef IMF_SCREENLOCK_MGR_ENABLE
4422736c2fSopenharmony_ci#include "screenlock_manager.h"
4522736c2fSopenharmony_ci#endif
4622736c2fSopenharmony_ci#include "system_language_observer.h"
4722736c2fSopenharmony_ci#include "user_session_manager.h"
4822736c2fSopenharmony_ci#include "wms_connection_observer.h"
4922736c2fSopenharmony_ci
5022736c2fSopenharmony_cinamespace OHOS {
5122736c2fSopenharmony_cinamespace MiscServices {
5222736c2fSopenharmony_ciusing namespace MessageID;
5322736c2fSopenharmony_ciusing namespace AppExecFwk;
5422736c2fSopenharmony_ciusing namespace Security::AccessToken;
5522736c2fSopenharmony_ciREGISTER_SYSTEM_ABILITY_BY_ID(InputMethodSystemAbility, INPUT_METHOD_SYSTEM_ABILITY_ID, true);
5622736c2fSopenharmony_ciconstexpr std::int32_t INIT_INTERVAL = 10000L;
5722736c2fSopenharmony_ciconstexpr const char *UNDEFINED = "undefined";
5822736c2fSopenharmony_cistatic const std::string PERMISSION_CONNECT_IME_ABILITY = "ohos.permission.CONNECT_IME_ABILITY";
5922736c2fSopenharmony_cistd::shared_ptr<AppExecFwk::EventHandler> InputMethodSystemAbility::serviceHandler_;
6022736c2fSopenharmony_ci
6122736c2fSopenharmony_ciInputMethodSystemAbility::InputMethodSystemAbility(int32_t systemAbilityId, bool runOnCreate)
6222736c2fSopenharmony_ci    : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START)
6322736c2fSopenharmony_ci{
6422736c2fSopenharmony_ci}
6522736c2fSopenharmony_ci
6622736c2fSopenharmony_ciInputMethodSystemAbility::InputMethodSystemAbility() : state_(ServiceRunningState::STATE_NOT_START)
6722736c2fSopenharmony_ci{
6822736c2fSopenharmony_ci}
6922736c2fSopenharmony_ci
7022736c2fSopenharmony_ciInputMethodSystemAbility::~InputMethodSystemAbility()
7122736c2fSopenharmony_ci{
7222736c2fSopenharmony_ci    stop_ = true;
7322736c2fSopenharmony_ci    Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
7422736c2fSopenharmony_ci    MessageHandler::Instance()->SendMessage(msg);
7522736c2fSopenharmony_ci    if (workThreadHandler.joinable()) {
7622736c2fSopenharmony_ci        workThreadHandler.join();
7722736c2fSopenharmony_ci    }
7822736c2fSopenharmony_ci}
7922736c2fSopenharmony_ci
8022736c2fSopenharmony_civoid InputMethodSystemAbility::OnStart()
8122736c2fSopenharmony_ci{
8222736c2fSopenharmony_ci    IMSA_HILOGI("InputMethodSystemAbility::OnStart start.");
8322736c2fSopenharmony_ci    if (!InputMethodSysEvent::GetInstance().StartTimerForReport()) {
8422736c2fSopenharmony_ci        IMSA_HILOGE("start sysevent timer failed!");
8522736c2fSopenharmony_ci    }
8622736c2fSopenharmony_ci    if (state_ == ServiceRunningState::STATE_RUNNING) {
8722736c2fSopenharmony_ci        IMSA_HILOGI("imsa service is already running.");
8822736c2fSopenharmony_ci        return;
8922736c2fSopenharmony_ci    }
9022736c2fSopenharmony_ci    InitServiceHandler();
9122736c2fSopenharmony_ci    Initialize();
9222736c2fSopenharmony_ci    int32_t ret = Init();
9322736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
9422736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().ServiceFaultReporter("imf", ret);
9522736c2fSopenharmony_ci        auto callback = [=]() { Init(); };
9622736c2fSopenharmony_ci        serviceHandler_->PostTask(callback, INIT_INTERVAL);
9722736c2fSopenharmony_ci        IMSA_HILOGE("init failed. try again 10s later!");
9822736c2fSopenharmony_ci    }
9922736c2fSopenharmony_ci    InitHiTrace();
10022736c2fSopenharmony_ci    InputMethodSyncTrace tracer("InputMethodController Attach trace.");
10122736c2fSopenharmony_ci    InputmethodDump::GetInstance().AddDumpAllMethod([this](int fd) { this->DumpAllMethod(fd); });
10222736c2fSopenharmony_ci    IMSA_HILOGI("start imsa service success.");
10322736c2fSopenharmony_ci    return;
10422736c2fSopenharmony_ci}
10522736c2fSopenharmony_ci
10622736c2fSopenharmony_ciint InputMethodSystemAbility::Dump(int fd, const std::vector<std::u16string> &args)
10722736c2fSopenharmony_ci{
10822736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility::Dump start.");
10922736c2fSopenharmony_ci    std::vector<std::string> argsStr;
11022736c2fSopenharmony_ci    for (auto item : args) {
11122736c2fSopenharmony_ci        argsStr.emplace_back(Str16ToStr8(item));
11222736c2fSopenharmony_ci    }
11322736c2fSopenharmony_ci    InputmethodDump::GetInstance().Dump(fd, argsStr);
11422736c2fSopenharmony_ci    return ERR_OK;
11522736c2fSopenharmony_ci}
11622736c2fSopenharmony_ci
11722736c2fSopenharmony_civoid InputMethodSystemAbility::DumpAllMethod(int fd)
11822736c2fSopenharmony_ci{
11922736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod start.");
12022736c2fSopenharmony_ci    auto ids = OsAccountAdapter::QueryActiveOsAccountIds();
12122736c2fSopenharmony_ci    if (ids.empty()) {
12222736c2fSopenharmony_ci        dprintf(fd, "\n - InputMethodSystemAbility::DumpAllMethod get Active Id failed.\n");
12322736c2fSopenharmony_ci        return;
12422736c2fSopenharmony_ci    }
12522736c2fSopenharmony_ci    dprintf(fd, "\n - DumpAllMethod get Active Id succeed,count=%zu,", ids.size());
12622736c2fSopenharmony_ci    for (auto id : ids) {
12722736c2fSopenharmony_ci        const auto &params = ImeInfoInquirer::GetInstance().GetDumpInfo(id);
12822736c2fSopenharmony_ci        if (params.empty()) {
12922736c2fSopenharmony_ci            IMSA_HILOGD("userId: %{public}d the IME properties is empty.", id);
13022736c2fSopenharmony_ci            dprintf(fd, "\n - The IME properties about the Active Id %d is empty.\n", id);
13122736c2fSopenharmony_ci            continue;
13222736c2fSopenharmony_ci        }
13322736c2fSopenharmony_ci        dprintf(fd, "\n - The Active Id:%d get input method:\n%s\n", id, params.c_str());
13422736c2fSopenharmony_ci    }
13522736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod end.");
13622736c2fSopenharmony_ci}
13722736c2fSopenharmony_ci
13822736c2fSopenharmony_ciint32_t InputMethodSystemAbility::Init()
13922736c2fSopenharmony_ci{
14022736c2fSopenharmony_ci    bool isSuccess = Publish(this);
14122736c2fSopenharmony_ci    if (!isSuccess) {
14222736c2fSopenharmony_ci        return -1;
14322736c2fSopenharmony_ci    }
14422736c2fSopenharmony_ci    state_ = ServiceRunningState::STATE_RUNNING;
14522736c2fSopenharmony_ci    ImeCfgManager::GetInstance().Init();
14622736c2fSopenharmony_ci    ImeInfoInquirer::GetInstance().InitSystemConfig();
14722736c2fSopenharmony_ci    InitMonitors();
14822736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
14922736c2fSopenharmony_ci}
15022736c2fSopenharmony_ci
15122736c2fSopenharmony_civoid InputMethodSystemAbility::UpdateUserInfo(int32_t userId)
15222736c2fSopenharmony_ci{
15322736c2fSopenharmony_ci    IMSA_HILOGI("%{public}d switch to %{public}d.", userId_, userId);
15422736c2fSopenharmony_ci    userId_ = userId;
15522736c2fSopenharmony_ci    UserSessionManager::GetInstance().AddUserSession(userId_);
15622736c2fSopenharmony_ci    InputMethodSysEvent::GetInstance().SetUserId(userId_);
15722736c2fSopenharmony_ci    if (enableImeOn_.load()) {
15822736c2fSopenharmony_ci        EnableImeDataParser::GetInstance()->OnUserChanged(userId_);
15922736c2fSopenharmony_ci    }
16022736c2fSopenharmony_ci    if (enableSecurityMode_.load()) {
16122736c2fSopenharmony_ci        SecurityModeParser::GetInstance()->UpdateFullModeList(userId_);
16222736c2fSopenharmony_ci    }
16322736c2fSopenharmony_ci}
16422736c2fSopenharmony_ci
16522736c2fSopenharmony_civoid InputMethodSystemAbility::OnStop()
16622736c2fSopenharmony_ci{
16722736c2fSopenharmony_ci    IMSA_HILOGI("OnStop start.");
16822736c2fSopenharmony_ci    FreezeManager::SetEventHandler(nullptr);
16922736c2fSopenharmony_ci    serviceHandler_ = nullptr;
17022736c2fSopenharmony_ci    state_ = ServiceRunningState::STATE_NOT_START;
17122736c2fSopenharmony_ci    Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 0, INPUT_METHOD_SYSTEM_ABILITY_ID);
17222736c2fSopenharmony_ci}
17322736c2fSopenharmony_ci
17422736c2fSopenharmony_civoid InputMethodSystemAbility::InitServiceHandler()
17522736c2fSopenharmony_ci{
17622736c2fSopenharmony_ci    IMSA_HILOGI("InitServiceHandler start.");
17722736c2fSopenharmony_ci    if (serviceHandler_ != nullptr) {
17822736c2fSopenharmony_ci        IMSA_HILOGE("InputMethodSystemAbility already init!");
17922736c2fSopenharmony_ci        return;
18022736c2fSopenharmony_ci    }
18122736c2fSopenharmony_ci    std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("OS_InputMethodSystemAbility");
18222736c2fSopenharmony_ci    serviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
18322736c2fSopenharmony_ci    FreezeManager::SetEventHandler(serviceHandler_);
18422736c2fSopenharmony_ci
18522736c2fSopenharmony_ci    IMSA_HILOGI("InitServiceHandler succeeded.");
18622736c2fSopenharmony_ci}
18722736c2fSopenharmony_ci
18822736c2fSopenharmony_ci/**
18922736c2fSopenharmony_ci * Initialization of Input method management service
19022736c2fSopenharmony_ci * \n It's called after the service starts, before any transaction.
19122736c2fSopenharmony_ci */
19222736c2fSopenharmony_civoid InputMethodSystemAbility::Initialize()
19322736c2fSopenharmony_ci{
19422736c2fSopenharmony_ci    IMSA_HILOGI("InputMethodSystemAbility::Initialize.");
19522736c2fSopenharmony_ci    // init work thread to handle the messages
19622736c2fSopenharmony_ci    workThreadHandler = std::thread([this] { this->WorkThread(); });
19722736c2fSopenharmony_ci    identityChecker_ = std::make_shared<IdentityCheckerImpl>();
19822736c2fSopenharmony_ci    userId_ = OsAccountAdapter::MAIN_USER_ID;
19922736c2fSopenharmony_ci    UserSessionManager::GetInstance().SetEventHandler(serviceHandler_);
20022736c2fSopenharmony_ci    UserSessionManager::GetInstance().AddUserSession(userId_);
20122736c2fSopenharmony_ci    InputMethodSysEvent::GetInstance().SetUserId(userId_);
20222736c2fSopenharmony_ci    isScbEnable_.store(Rosen::SceneBoardJudgement::IsSceneBoardEnabled());
20322736c2fSopenharmony_ci}
20422736c2fSopenharmony_ci
20522736c2fSopenharmony_civoid InputMethodSystemAbility::SubscribeCommonEvent()
20622736c2fSopenharmony_ci{
20722736c2fSopenharmony_ci    sptr<ImCommonEventManager> imCommonEventManager = ImCommonEventManager::GetInstance();
20822736c2fSopenharmony_ci    bool isSuccess = imCommonEventManager->SubscribeEvent();
20922736c2fSopenharmony_ci    if (isSuccess) {
21022736c2fSopenharmony_ci        IMSA_HILOGI("initialize subscribe service event success.");
21122736c2fSopenharmony_ci        return;
21222736c2fSopenharmony_ci    }
21322736c2fSopenharmony_ci
21422736c2fSopenharmony_ci    IMSA_HILOGE("failed, try again 10s later!");
21522736c2fSopenharmony_ci    auto callback = [this]() { SubscribeCommonEvent(); };
21622736c2fSopenharmony_ci    serviceHandler_->PostTask(callback, INIT_INTERVAL);
21722736c2fSopenharmony_ci}
21822736c2fSopenharmony_ci
21922736c2fSopenharmony_ciint32_t InputMethodSystemAbility::PrepareInput(int32_t userId, InputClientInfo &clientInfo)
22022736c2fSopenharmony_ci{
22122736c2fSopenharmony_ci    auto ret = GenerateClientInfo(userId, clientInfo);
22222736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
22322736c2fSopenharmony_ci        return ret;
22422736c2fSopenharmony_ci    }
22522736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
22622736c2fSopenharmony_ci    if (session == nullptr) {
22722736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
22822736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
22922736c2fSopenharmony_ci    }
23022736c2fSopenharmony_ci    return session->OnPrepareInput(clientInfo);
23122736c2fSopenharmony_ci}
23222736c2fSopenharmony_ci
23322736c2fSopenharmony_ciint32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClientInfo &clientInfo)
23422736c2fSopenharmony_ci{
23522736c2fSopenharmony_ci    if (clientInfo.client == nullptr || clientInfo.channel == nullptr) {
23622736c2fSopenharmony_ci        IMSA_HILOGE("client or channel is nullptr!");
23722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
23822736c2fSopenharmony_ci    }
23922736c2fSopenharmony_ci    auto deathRecipient = new (std::nothrow) InputDeathRecipient();
24022736c2fSopenharmony_ci    if (deathRecipient == nullptr) {
24122736c2fSopenharmony_ci        IMSA_HILOGE("failed to new deathRecipient!");
24222736c2fSopenharmony_ci        return ErrorCode::ERROR_EX_NULL_POINTER;
24322736c2fSopenharmony_ci    }
24422736c2fSopenharmony_ci    clientInfo.pid = IPCSkeleton::GetCallingPid();
24522736c2fSopenharmony_ci    clientInfo.uid = IPCSkeleton::GetCallingUid();
24622736c2fSopenharmony_ci    clientInfo.userID = userId;
24722736c2fSopenharmony_ci    clientInfo.deathRecipient = deathRecipient;
24822736c2fSopenharmony_ci    auto tokenId = IPCSkeleton::GetCallingTokenID();
24922736c2fSopenharmony_ci    if (identityChecker_->IsFocusedUIExtension(tokenId)) {
25022736c2fSopenharmony_ci        clientInfo.uiExtensionTokenId = tokenId;
25122736c2fSopenharmony_ci    }
25222736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
25322736c2fSopenharmony_ci}
25422736c2fSopenharmony_ci
25522736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ReleaseInput(sptr<IInputClient> client)
25622736c2fSopenharmony_ci{
25722736c2fSopenharmony_ci    if (client == nullptr) {
25822736c2fSopenharmony_ci        IMSA_HILOGE("client is nullptr!");
25922736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
26022736c2fSopenharmony_ci    }
26122736c2fSopenharmony_ci    auto userId = GetCallingUserId();
26222736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
26322736c2fSopenharmony_ci    if (session == nullptr) {
26422736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
26522736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
26622736c2fSopenharmony_ci    }
26722736c2fSopenharmony_ci    return session->OnReleaseInput(client);
26822736c2fSopenharmony_ci}
26922736c2fSopenharmony_ci
27022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::StartInput(InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
27122736c2fSopenharmony_ci{
27222736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
27322736c2fSopenharmony_ci    if (!identityChecker_->IsBroker(tokenId) && !identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)) {
27422736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
27522736c2fSopenharmony_ci    }
27622736c2fSopenharmony_ci    auto userId = GetCallingUserId();
27722736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
27822736c2fSopenharmony_ci    if (session == nullptr) {
27922736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
28022736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
28122736c2fSopenharmony_ci    }
28222736c2fSopenharmony_ci    if (session->GetCurrentClientPid() != IPCSkeleton::GetCallingPid()
28322736c2fSopenharmony_ci        && session->GetInactiveClientPid() != IPCSkeleton::GetCallingPid()) {
28422736c2fSopenharmony_ci        // notify inputStart when caller pid different from both current client and inactive client
28522736c2fSopenharmony_ci        inputClientInfo.isNotifyInputStart = true;
28622736c2fSopenharmony_ci    }
28722736c2fSopenharmony_ci    if (inputClientInfo.isNotifyInputStart) {
28822736c2fSopenharmony_ci        inputClientInfo.needHide = session->CheckPwdInputPatternConv(inputClientInfo);
28922736c2fSopenharmony_ci    }
29022736c2fSopenharmony_ci    if (!session->IsProxyImeEnable()) {
29122736c2fSopenharmony_ci        auto ret = CheckInputTypeOption(userId, inputClientInfo);
29222736c2fSopenharmony_ci        if (ret != ErrorCode::NO_ERROR) {
29322736c2fSopenharmony_ci            IMSA_HILOGE("%{public}d failed to CheckInputTypeOption!", userId);
29422736c2fSopenharmony_ci            return ret;
29522736c2fSopenharmony_ci        }
29622736c2fSopenharmony_ci    }
29722736c2fSopenharmony_ci    int32_t ret = PrepareInput(userId, inputClientInfo);
29822736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
29922736c2fSopenharmony_ci        IMSA_HILOGE("failed to PrepareInput!");
30022736c2fSopenharmony_ci        return ret;
30122736c2fSopenharmony_ci    }
30222736c2fSopenharmony_ci    session->SetInputType();
30322736c2fSopenharmony_ci    return session->OnStartInput(inputClientInfo, agent);
30422736c2fSopenharmony_ci}
30522736c2fSopenharmony_ci
30622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::CheckInputTypeOption(int32_t userId, InputClientInfo &inputClientInfo)
30722736c2fSopenharmony_ci{
30822736c2fSopenharmony_ci    IMSA_HILOGI("SecurityFlag: %{public}d, IsSameTextInput: %{public}d, IsStarted: %{public}d, "
30922736c2fSopenharmony_ci                "IsSecurityImeStarted: %{public}d.",
31022736c2fSopenharmony_ci        inputClientInfo.config.inputAttribute.GetSecurityFlag(), !inputClientInfo.isNotifyInputStart,
31122736c2fSopenharmony_ci        InputTypeManager::GetInstance().IsStarted(), InputTypeManager::GetInstance().IsSecurityImeStarted());
31222736c2fSopenharmony_ci    if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) {
31322736c2fSopenharmony_ci        if (!InputTypeManager::GetInstance().IsStarted()) {
31422736c2fSopenharmony_ci            IMSA_HILOGD("SecurityFlag, input type is not started, start.");
31522736c2fSopenharmony_ci            // if need to switch ime, no need to hide panel first.
31622736c2fSopenharmony_ci            NeedHideWhenSwitchInputType(userId, inputClientInfo.needHide);
31722736c2fSopenharmony_ci            return StartInputType(userId, InputType::SECURITY_INPUT);
31822736c2fSopenharmony_ci        }
31922736c2fSopenharmony_ci        if (!inputClientInfo.isNotifyInputStart) {
32022736c2fSopenharmony_ci            IMSA_HILOGD("SecurityFlag, same textField, input type is started, not deal.");
32122736c2fSopenharmony_ci            return ErrorCode::NO_ERROR;
32222736c2fSopenharmony_ci        }
32322736c2fSopenharmony_ci        if (!InputTypeManager::GetInstance().IsSecurityImeStarted()) {
32422736c2fSopenharmony_ci            IMSA_HILOGD("SecurityFlag, new textField, input type is started, but it is not security, switch.");
32522736c2fSopenharmony_ci            NeedHideWhenSwitchInputType(userId, inputClientInfo.needHide);
32622736c2fSopenharmony_ci            return StartInputType(userId, InputType::SECURITY_INPUT);
32722736c2fSopenharmony_ci        }
32822736c2fSopenharmony_ci        IMSA_HILOGD("SecurityFlag, other condition, not deal.");
32922736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
33022736c2fSopenharmony_ci    }
33122736c2fSopenharmony_ci    if (!inputClientInfo.isNotifyInputStart) {
33222736c2fSopenharmony_ci        IMSA_HILOGD("NormalFlag, same textField, not deal.");
33322736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
33422736c2fSopenharmony_ci    }
33522736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
33622736c2fSopenharmony_ci    if (session == nullptr) {
33722736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
33822736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
33922736c2fSopenharmony_ci    }
34022736c2fSopenharmony_ci    if (InputTypeManager::GetInstance().IsStarted()) {
34122736c2fSopenharmony_ci        IMSA_HILOGD("NormalFlag, diff textField, input type started, restore.");
34222736c2fSopenharmony_ci        session->RestoreCurrentImeSubType();
34322736c2fSopenharmony_ci    }
34422736c2fSopenharmony_ci    return session->RestoreCurrentIme();
34522736c2fSopenharmony_ci}
34622736c2fSopenharmony_ci
34722736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ShowInput(sptr<IInputClient> client)
34822736c2fSopenharmony_ci{
34922736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
35022736c2fSopenharmony_ci    auto userId = GetCallingUserId();
35122736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
35222736c2fSopenharmony_ci    if (session == nullptr) {
35322736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
35422736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
35522736c2fSopenharmony_ci    }
35622736c2fSopenharmony_ci    if (!identityChecker_->IsBroker(tokenId)) {
35722736c2fSopenharmony_ci        if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
35822736c2fSopenharmony_ci            return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
35922736c2fSopenharmony_ci        }
36022736c2fSopenharmony_ci    }
36122736c2fSopenharmony_ci    if (client == nullptr) {
36222736c2fSopenharmony_ci        IMSA_HILOGE("client is nullptr!");
36322736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
36422736c2fSopenharmony_ci    }
36522736c2fSopenharmony_ci    return session->OnShowInput(client);
36622736c2fSopenharmony_ci}
36722736c2fSopenharmony_ci
36822736c2fSopenharmony_ciint32_t InputMethodSystemAbility::HideInput(sptr<IInputClient> client)
36922736c2fSopenharmony_ci{
37022736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
37122736c2fSopenharmony_ci    auto userId = GetCallingUserId();
37222736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
37322736c2fSopenharmony_ci    if (session == nullptr) {
37422736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
37522736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
37622736c2fSopenharmony_ci    }
37722736c2fSopenharmony_ci    if (!identityChecker_->IsBroker(tokenId)) {
37822736c2fSopenharmony_ci        if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
37922736c2fSopenharmony_ci            return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
38022736c2fSopenharmony_ci        }
38122736c2fSopenharmony_ci    }
38222736c2fSopenharmony_ci    if (client == nullptr) {
38322736c2fSopenharmony_ci        IMSA_HILOGE("client is nullptr!");
38422736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
38522736c2fSopenharmony_ci    }
38622736c2fSopenharmony_ci    return session->OnHideInput(client);
38722736c2fSopenharmony_ci}
38822736c2fSopenharmony_ci
38922736c2fSopenharmony_ciint32_t InputMethodSystemAbility::StopInputSession()
39022736c2fSopenharmony_ci{
39122736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
39222736c2fSopenharmony_ci    auto userId = GetCallingUserId();
39322736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
39422736c2fSopenharmony_ci    if (session == nullptr) {
39522736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
39622736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
39722736c2fSopenharmony_ci    }
39822736c2fSopenharmony_ci    if (!identityChecker_->IsBroker(tokenId)) {
39922736c2fSopenharmony_ci        if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
40022736c2fSopenharmony_ci            return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
40122736c2fSopenharmony_ci        }
40222736c2fSopenharmony_ci    }
40322736c2fSopenharmony_ci    return session->OnHideCurrentInput();
40422736c2fSopenharmony_ci}
40522736c2fSopenharmony_ci
40622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::RequestShowInput()
40722736c2fSopenharmony_ci{
40822736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
40922736c2fSopenharmony_ci    if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) &&
41022736c2fSopenharmony_ci        !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
41122736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
41222736c2fSopenharmony_ci    }
41322736c2fSopenharmony_ci    auto userId = GetCallingUserId();
41422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
41522736c2fSopenharmony_ci    if (session == nullptr) {
41622736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
41722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
41822736c2fSopenharmony_ci    }
41922736c2fSopenharmony_ci    return session->OnRequestShowInput();
42022736c2fSopenharmony_ci}
42122736c2fSopenharmony_ci
42222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::RequestHideInput()
42322736c2fSopenharmony_ci{
42422736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
42522736c2fSopenharmony_ci    if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) &&
42622736c2fSopenharmony_ci        !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
42722736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
42822736c2fSopenharmony_ci    }
42922736c2fSopenharmony_ci    auto userId = GetCallingUserId();
43022736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
43122736c2fSopenharmony_ci    if (session == nullptr) {
43222736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
43322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
43422736c2fSopenharmony_ci    }
43522736c2fSopenharmony_ci    return session->OnRequestHideInput();
43622736c2fSopenharmony_ci}
43722736c2fSopenharmony_ci
43822736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
43922736c2fSopenharmony_ci{
44022736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility start.");
44122736c2fSopenharmony_ci    auto userId = GetCallingUserId();
44222736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
44322736c2fSopenharmony_ci    if (session == nullptr) {
44422736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
44522736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
44622736c2fSopenharmony_ci    }
44722736c2fSopenharmony_ci    if (identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
44822736c2fSopenharmony_ci        return session->OnRegisterProxyIme(core, agent);
44922736c2fSopenharmony_ci    }
45022736c2fSopenharmony_ci    if (!IsCurrentIme(userId)) {
45122736c2fSopenharmony_ci        IMSA_HILOGE("not current ime, userId:%{public}d", userId);
45222736c2fSopenharmony_ci        return ErrorCode::ERROR_NOT_CURRENT_IME;
45322736c2fSopenharmony_ci    }
45422736c2fSopenharmony_ci    return session->OnSetCoreAndAgent(core, agent);
45522736c2fSopenharmony_ci}
45622736c2fSopenharmony_ci
45722736c2fSopenharmony_ciint32_t InputMethodSystemAbility::InitConnect()
45822736c2fSopenharmony_ci{
45922736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility init connect.");
46022736c2fSopenharmony_ci    auto userId = GetCallingUserId();
46122736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
46222736c2fSopenharmony_ci    if (session == nullptr) {
46322736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
46422736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
46522736c2fSopenharmony_ci    }
46622736c2fSopenharmony_ci    if (!IsCurrentIme(userId)) {
46722736c2fSopenharmony_ci        return ErrorCode::ERROR_NOT_CURRENT_IME;
46822736c2fSopenharmony_ci    }
46922736c2fSopenharmony_ci    return session->InitConnect(IPCSkeleton::GetCallingPid());
47022736c2fSopenharmony_ci}
47122736c2fSopenharmony_ci
47222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::HideCurrentInput()
47322736c2fSopenharmony_ci{
47422736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
47522736c2fSopenharmony_ci    auto userId = GetCallingUserId();
47622736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
47722736c2fSopenharmony_ci    if (session == nullptr) {
47822736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
47922736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
48022736c2fSopenharmony_ci    }
48122736c2fSopenharmony_ci    if (identityChecker_->IsBroker(tokenId)) {
48222736c2fSopenharmony_ci        return session->OnHideCurrentInput();
48322736c2fSopenharmony_ci    }
48422736c2fSopenharmony_ci    if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
48522736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
48622736c2fSopenharmony_ci    }
48722736c2fSopenharmony_ci    return session->OnHideCurrentInput();
48822736c2fSopenharmony_ci}
48922736c2fSopenharmony_ci
49022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ShowCurrentInput()
49122736c2fSopenharmony_ci{
49222736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
49322736c2fSopenharmony_ci    auto userId = GetCallingUserId();
49422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
49522736c2fSopenharmony_ci    if (session == nullptr) {
49622736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
49722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
49822736c2fSopenharmony_ci    }
49922736c2fSopenharmony_ci    if (identityChecker_->IsBroker(tokenId)) {
50022736c2fSopenharmony_ci        return session->OnShowCurrentInput();
50122736c2fSopenharmony_ci    }
50222736c2fSopenharmony_ci    if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
50322736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
50422736c2fSopenharmony_ci    }
50522736c2fSopenharmony_ci    return session->OnShowCurrentInput();
50622736c2fSopenharmony_ci}
50722736c2fSopenharmony_ci
50822736c2fSopenharmony_ciint32_t InputMethodSystemAbility::PanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info)
50922736c2fSopenharmony_ci{
51022736c2fSopenharmony_ci    auto userId = GetCallingUserId();
51122736c2fSopenharmony_ci    if (!IsCurrentIme(userId)) {
51222736c2fSopenharmony_ci        IMSA_HILOGE("not current ime!");
51322736c2fSopenharmony_ci        return ErrorCode::ERROR_NOT_CURRENT_IME;
51422736c2fSopenharmony_ci    }
51522736c2fSopenharmony_ci    auto commonEventManager = ImCommonEventManager::GetInstance();
51622736c2fSopenharmony_ci    if (commonEventManager != nullptr) {
51722736c2fSopenharmony_ci        auto ret = ImCommonEventManager::GetInstance()->PublishPanelStatusChangeEvent(userId, status, info);
51822736c2fSopenharmony_ci        IMSA_HILOGD("public panel status change event: %{public}d", ret);
51922736c2fSopenharmony_ci    }
52022736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
52122736c2fSopenharmony_ci    if (session == nullptr) {
52222736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
52322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
52422736c2fSopenharmony_ci    }
52522736c2fSopenharmony_ci    return session->OnPanelStatusChange(status, info);
52622736c2fSopenharmony_ci}
52722736c2fSopenharmony_ci
52822736c2fSopenharmony_ciint32_t InputMethodSystemAbility::UpdateListenEventFlag(InputClientInfo &clientInfo, uint32_t eventFlag)
52922736c2fSopenharmony_ci{
53022736c2fSopenharmony_ci    IMSA_HILOGI("finalEventFlag: %{public}u, eventFlag: %{public}u.", clientInfo.eventFlag, eventFlag);
53122736c2fSopenharmony_ci    if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag)) {
53222736c2fSopenharmony_ci        if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
53322736c2fSopenharmony_ci            !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
53422736c2fSopenharmony_ci            IMSA_HILOGE("not system application!");
53522736c2fSopenharmony_ci            return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
53622736c2fSopenharmony_ci        }
53722736c2fSopenharmony_ci    }
53822736c2fSopenharmony_ci    auto userId = GetCallingUserId();
53922736c2fSopenharmony_ci    auto ret = GenerateClientInfo(userId, clientInfo);
54022736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
54122736c2fSopenharmony_ci        return ret;
54222736c2fSopenharmony_ci    }
54322736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
54422736c2fSopenharmony_ci    if (session == nullptr) {
54522736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
54622736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
54722736c2fSopenharmony_ci    }
54822736c2fSopenharmony_ci    return session->OnUpdateListenEventFlag(clientInfo);
54922736c2fSopenharmony_ci}
55022736c2fSopenharmony_ci
55122736c2fSopenharmony_cibool InputMethodSystemAbility::IsCurrentIme()
55222736c2fSopenharmony_ci{
55322736c2fSopenharmony_ci    return IsCurrentIme(GetCallingUserId());
55422736c2fSopenharmony_ci}
55522736c2fSopenharmony_ci
55622736c2fSopenharmony_cibool InputMethodSystemAbility::IsInputTypeSupported(InputType type)
55722736c2fSopenharmony_ci{
55822736c2fSopenharmony_ci    return InputTypeManager::GetInstance().IsSupported(type);
55922736c2fSopenharmony_ci}
56022736c2fSopenharmony_ci
56122736c2fSopenharmony_ciint32_t InputMethodSystemAbility::StartInputType(InputType type)
56222736c2fSopenharmony_ci{
56322736c2fSopenharmony_ci    return StartInputType(GetCallingUserId(), type);
56422736c2fSopenharmony_ci}
56522736c2fSopenharmony_ci
56622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ExitCurrentInputType()
56722736c2fSopenharmony_ci{
56822736c2fSopenharmony_ci    auto userId = GetCallingUserId();
56922736c2fSopenharmony_ci    auto ret = IsDefaultImeFromTokenId(userId, IPCSkeleton::GetCallingTokenID());
57022736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
57122736c2fSopenharmony_ci        IMSA_HILOGE("not default ime!");
57222736c2fSopenharmony_ci        return ErrorCode::ERROR_NOT_DEFAULT_IME;
57322736c2fSopenharmony_ci    }
57422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
57522736c2fSopenharmony_ci    if (session == nullptr) {
57622736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
57722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
57822736c2fSopenharmony_ci    }
57922736c2fSopenharmony_ci    if (session->CheckSecurityMode()) {
58022736c2fSopenharmony_ci        return StartInputType(userId, InputType::SECURITY_INPUT);
58122736c2fSopenharmony_ci    }
58222736c2fSopenharmony_ci    auto typeIme = InputTypeManager::GetInstance().GetCurrentIme();
58322736c2fSopenharmony_ci    auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
58422736c2fSopenharmony_ci    if (cfgIme->bundleName == typeIme.bundleName) {
58522736c2fSopenharmony_ci        return session->RestoreCurrentImeSubType();
58622736c2fSopenharmony_ci    }
58722736c2fSopenharmony_ci    return session->RestoreCurrentIme();
58822736c2fSopenharmony_ci}
58922736c2fSopenharmony_ci
59022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::IsDefaultIme()
59122736c2fSopenharmony_ci{
59222736c2fSopenharmony_ci    return IsDefaultImeFromTokenId(GetCallingUserId(), IPCSkeleton::GetCallingTokenID());
59322736c2fSopenharmony_ci}
59422736c2fSopenharmony_ci
59522736c2fSopenharmony_ciint32_t InputMethodSystemAbility::IsDefaultImeFromTokenId(int32_t userId, uint32_t tokenId)
59622736c2fSopenharmony_ci{
59722736c2fSopenharmony_ci    auto prop = std::make_shared<Property>();
59822736c2fSopenharmony_ci    auto ret = ImeInfoInquirer::GetInstance().GetDefaultInputMethod(userId, prop);
59922736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR || prop == nullptr) {
60022736c2fSopenharmony_ci        IMSA_HILOGE("failed to get default ime!");
60122736c2fSopenharmony_ci        return ErrorCode::ERROR_PERSIST_CONFIG;
60222736c2fSopenharmony_ci    }
60322736c2fSopenharmony_ci    if (!identityChecker_->IsBundleNameValid(tokenId, prop->name)) {
60422736c2fSopenharmony_ci        return ErrorCode::ERROR_NOT_DEFAULT_IME;
60522736c2fSopenharmony_ci    }
60622736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
60722736c2fSopenharmony_ci}
60822736c2fSopenharmony_ci
60922736c2fSopenharmony_cibool InputMethodSystemAbility::IsCurrentImeByPid(int32_t pid)
61022736c2fSopenharmony_ci{
61122736c2fSopenharmony_ci    if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
61222736c2fSopenharmony_ci        !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
61322736c2fSopenharmony_ci        IMSA_HILOGE("not system application or system ability!");
61422736c2fSopenharmony_ci        return false;
61522736c2fSopenharmony_ci    }
61622736c2fSopenharmony_ci    auto userId = GetCallingUserId();
61722736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
61822736c2fSopenharmony_ci    if (session == nullptr) {
61922736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
62022736c2fSopenharmony_ci        return false;
62122736c2fSopenharmony_ci    }
62222736c2fSopenharmony_ci    return session->IsCurrentImeByPid(pid);
62322736c2fSopenharmony_ci}
62422736c2fSopenharmony_ci
62522736c2fSopenharmony_ciint32_t InputMethodSystemAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
62622736c2fSopenharmony_ci{
62722736c2fSopenharmony_ci    if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
62822736c2fSopenharmony_ci        IMSA_HILOGE("not system application!");
62922736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
63022736c2fSopenharmony_ci    }
63122736c2fSopenharmony_ci    auto userId = GetCallingUserId();
63222736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
63322736c2fSopenharmony_ci    if (session == nullptr) {
63422736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
63522736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
63622736c2fSopenharmony_ci    }
63722736c2fSopenharmony_ci    return session->IsPanelShown(panelInfo, isShown);
63822736c2fSopenharmony_ci}
63922736c2fSopenharmony_ci
64022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::DisplayOptionalInputMethod()
64122736c2fSopenharmony_ci{
64222736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility start.");
64322736c2fSopenharmony_ci    return OnDisplayOptionalInputMethod();
64422736c2fSopenharmony_ci}
64522736c2fSopenharmony_ci
64622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleName, const std::string &subName,
64722736c2fSopenharmony_ci    SwitchTrigger trigger)
64822736c2fSopenharmony_ci{
64922736c2fSopenharmony_ci    // IMSA not check permission, add this verify for prevent counterfeit
65022736c2fSopenharmony_ci    if (trigger == SwitchTrigger::IMSA) {
65122736c2fSopenharmony_ci        IMSA_HILOGW("caller counterfeit!");
65222736c2fSopenharmony_ci        return ErrorCode::ERROR_BAD_PARAMETERS;
65322736c2fSopenharmony_ci    }
65422736c2fSopenharmony_ci    SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, subName };
65522736c2fSopenharmony_ci    int32_t userId = GetCallingUserId();
65622736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
65722736c2fSopenharmony_ci    if (session == nullptr) {
65822736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
65922736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
66022736c2fSopenharmony_ci    }
66122736c2fSopenharmony_ci    if (enableImeOn_.load() && !EnableImeDataParser::GetInstance()->CheckNeedSwitch(switchInfo, userId)) {
66222736c2fSopenharmony_ci        IMSA_HILOGW("Enable mode off or switch is not enable, stopped!");
66322736c2fSopenharmony_ci        return ErrorCode::ERROR_ENABLE_IME;
66422736c2fSopenharmony_ci    }
66522736c2fSopenharmony_ci    auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
66622736c2fSopenharmony_ci    if (switchInfo.subName.empty() && switchInfo.bundleName == currentImeCfg->bundleName) {
66722736c2fSopenharmony_ci        switchInfo.subName = currentImeCfg->subName;
66822736c2fSopenharmony_ci    }
66922736c2fSopenharmony_ci    switchInfo.timestamp = std::chrono::system_clock::now();
67022736c2fSopenharmony_ci    session->GetSwitchQueue().Push(switchInfo);
67122736c2fSopenharmony_ci    return InputTypeManager::GetInstance().IsInputType({ bundleName, subName })
67222736c2fSopenharmony_ci               ? OnStartInputType(userId, switchInfo, true)
67322736c2fSopenharmony_ci               : OnSwitchInputMethod(userId, switchInfo, trigger);
67422736c2fSopenharmony_ci}
67522736c2fSopenharmony_ci
67622736c2fSopenharmony_cibool InputMethodSystemAbility::EnableIme(const std::string &bundleName)
67722736c2fSopenharmony_ci{
67822736c2fSopenharmony_ci    if (CheckEnableAndSwitchPermission() != ErrorCode::NO_ERROR) {
67922736c2fSopenharmony_ci        IMSA_HILOGE("Check enable ime value failed!");
68022736c2fSopenharmony_ci        return false;
68122736c2fSopenharmony_ci    }
68222736c2fSopenharmony_ci    int32_t userId = GetCallingUserId();
68322736c2fSopenharmony_ci    return SettingsDataUtils::GetInstance()->EnableIme(userId, bundleName);
68422736c2fSopenharmony_ci}
68522736c2fSopenharmony_ci
68622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnSwitchInputMethod(int32_t userId, const SwitchInfo &switchInfo,
68722736c2fSopenharmony_ci    SwitchTrigger trigger)
68822736c2fSopenharmony_ci{
68922736c2fSopenharmony_ci    InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::CHANGE_IME);
69022736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
69122736c2fSopenharmony_ci    if (session == nullptr) {
69222736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
69322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
69422736c2fSopenharmony_ci    }
69522736c2fSopenharmony_ci    if (!session->GetSwitchQueue().IsReady(switchInfo)) {
69622736c2fSopenharmony_ci        IMSA_HILOGD("start wait.");
69722736c2fSopenharmony_ci        session->GetSwitchQueue().Wait(switchInfo);
69822736c2fSopenharmony_ci    }
69922736c2fSopenharmony_ci    IMSA_HILOGI("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
70022736c2fSopenharmony_ci    int32_t ret = CheckSwitchPermission(userId, switchInfo, trigger);
70122736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
70222736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_STATUS_PERMISSION_DENIED,
70322736c2fSopenharmony_ci            switchInfo.bundleName, "switch input method failed!");
70422736c2fSopenharmony_ci        session->GetSwitchQueue().Pop();
70522736c2fSopenharmony_ci        return ret;
70622736c2fSopenharmony_ci    }
70722736c2fSopenharmony_ci    auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId, switchInfo.bundleName, switchInfo.subName);
70822736c2fSopenharmony_ci    if (info == nullptr) {
70922736c2fSopenharmony_ci        session->GetSwitchQueue().Pop();
71022736c2fSopenharmony_ci        return ErrorCode::ERROR_BAD_PARAMETERS;
71122736c2fSopenharmony_ci    }
71222736c2fSopenharmony_ci    InputTypeManager::GetInstance().Set(false);
71322736c2fSopenharmony_ci    {
71422736c2fSopenharmony_ci        InputMethodSyncTrace tracer("InputMethodSystemAbility_OnSwitchInputMethod");
71522736c2fSopenharmony_ci        std::string targetImeName = info->prop.name + "/" + info->prop.id;
71622736c2fSopenharmony_ci        ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, true });
71722736c2fSopenharmony_ci        auto targetIme = std::make_shared<ImeNativeCfg>(ImeNativeCfg {
71822736c2fSopenharmony_ci            targetImeName, info->prop.name, switchInfo.subName.empty() ? "" : info->subProp.id, info->prop.id });
71922736c2fSopenharmony_ci        if (!session->StartIme(targetIme)) {
72022736c2fSopenharmony_ci            InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, switchInfo.bundleName,
72122736c2fSopenharmony_ci                "switch input method failed!");
72222736c2fSopenharmony_ci            session->GetSwitchQueue().Pop();
72322736c2fSopenharmony_ci            return ErrorCode::ERROR_IME_START_FAILED;
72422736c2fSopenharmony_ci        }
72522736c2fSopenharmony_ci        GetValidSubtype(switchInfo.subName, info);
72622736c2fSopenharmony_ci        session->NotifyImeChangeToClients(info->prop, info->subProp);
72722736c2fSopenharmony_ci        ret = session->SwitchSubtype(info->subProp);
72822736c2fSopenharmony_ci    }
72922736c2fSopenharmony_ci    session->GetSwitchQueue().Pop();
73022736c2fSopenharmony_ci    ret = info->isSpecificSubName ? ret : ErrorCode::NO_ERROR;
73122736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
73222736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, switchInfo.bundleName,
73322736c2fSopenharmony_ci            "switch input method subtype failed!");
73422736c2fSopenharmony_ci    }
73522736c2fSopenharmony_ci    return ret;
73622736c2fSopenharmony_ci}
73722736c2fSopenharmony_ci
73822736c2fSopenharmony_civoid InputMethodSystemAbility::GetValidSubtype(const std::string &subName, const std::shared_ptr<ImeInfo> &info)
73922736c2fSopenharmony_ci{
74022736c2fSopenharmony_ci    if (subName.empty()) {
74122736c2fSopenharmony_ci        IMSA_HILOGW("undefined subtype");
74222736c2fSopenharmony_ci        info->subProp.id = UNDEFINED;
74322736c2fSopenharmony_ci        info->subProp.name = UNDEFINED;
74422736c2fSopenharmony_ci    }
74522736c2fSopenharmony_ci}
74622736c2fSopenharmony_ci
74722736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnStartInputType(int32_t userId, const SwitchInfo &switchInfo,
74822736c2fSopenharmony_ci    bool isCheckPermission)
74922736c2fSopenharmony_ci{
75022736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
75122736c2fSopenharmony_ci    if (session == nullptr) {
75222736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
75322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
75422736c2fSopenharmony_ci    }
75522736c2fSopenharmony_ci    if (!session->GetSwitchQueue().IsReady(switchInfo)) {
75622736c2fSopenharmony_ci        IMSA_HILOGD("start wait.");
75722736c2fSopenharmony_ci        session->GetSwitchQueue().Wait(switchInfo);
75822736c2fSopenharmony_ci    }
75922736c2fSopenharmony_ci    IMSA_HILOGD("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
76022736c2fSopenharmony_ci    if (isCheckPermission && !IsStartInputTypePermitted(userId)) {
76122736c2fSopenharmony_ci        IMSA_HILOGE("not permitted to start input type!");
76222736c2fSopenharmony_ci        session->GetSwitchQueue().Pop();
76322736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
76422736c2fSopenharmony_ci    }
76522736c2fSopenharmony_ci    if (!IsNeedSwitch(userId, switchInfo.bundleName, switchInfo.subName)) {
76622736c2fSopenharmony_ci        IMSA_HILOGI("no need to switch.");
76722736c2fSopenharmony_ci        session->GetSwitchQueue().Pop();
76822736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
76922736c2fSopenharmony_ci    }
77022736c2fSopenharmony_ci    int32_t ret = SwitchInputType(userId, switchInfo);
77122736c2fSopenharmony_ci    session->GetSwitchQueue().Pop();
77222736c2fSopenharmony_ci    return ret;
77322736c2fSopenharmony_ci}
77422736c2fSopenharmony_ci
77522736c2fSopenharmony_cibool InputMethodSystemAbility::IsNeedSwitch(int32_t userId, const std::string &bundleName,
77622736c2fSopenharmony_ci    const std::string &subName)
77722736c2fSopenharmony_ci{
77822736c2fSopenharmony_ci    if (InputTypeManager::GetInstance().IsStarted()) {
77922736c2fSopenharmony_ci        ImeIdentification target = { bundleName, subName };
78022736c2fSopenharmony_ci        return !(target == InputTypeManager::GetInstance().GetCurrentIme());
78122736c2fSopenharmony_ci    }
78222736c2fSopenharmony_ci    auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
78322736c2fSopenharmony_ci    IMSA_HILOGI("currentIme: %{public}s/%{public}s, targetIme: %{public}s/%{public}s.",
78422736c2fSopenharmony_ci        currentImeCfg->bundleName.c_str(), currentImeCfg->subName.c_str(), bundleName.c_str(), subName.c_str());
78522736c2fSopenharmony_ci    if ((subName.empty() && bundleName == currentImeCfg->bundleName) ||
78622736c2fSopenharmony_ci        (!subName.empty() && subName == currentImeCfg->subName && currentImeCfg->bundleName == bundleName)) {
78722736c2fSopenharmony_ci        IMSA_HILOGI("no need to switch.");
78822736c2fSopenharmony_ci        return false;
78922736c2fSopenharmony_ci    }
79022736c2fSopenharmony_ci    return true;
79122736c2fSopenharmony_ci}
79222736c2fSopenharmony_ci
79322736c2fSopenharmony_ciint32_t InputMethodSystemAbility::Switch(int32_t userId, const std::string &bundleName,
79422736c2fSopenharmony_ci    const std::shared_ptr<ImeInfo> &info)
79522736c2fSopenharmony_ci{
79622736c2fSopenharmony_ci    auto currentImeBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
79722736c2fSopenharmony_ci    if (bundleName != currentImeBundleName) {
79822736c2fSopenharmony_ci        IMSA_HILOGI("switch input method to: %{public}s", bundleName.c_str());
79922736c2fSopenharmony_ci        return SwitchExtension(userId, info);
80022736c2fSopenharmony_ci    }
80122736c2fSopenharmony_ci    auto currentInputType = InputTypeManager::GetInstance().GetCurrentIme();
80222736c2fSopenharmony_ci    auto isInputTypeStarted = InputTypeManager::GetInstance().IsStarted();
80322736c2fSopenharmony_ci    if (isInputTypeStarted && bundleName != currentInputType.bundleName) {
80422736c2fSopenharmony_ci        IMSA_HILOGI("right click on state, switch input method to: %{public}s", bundleName.c_str());
80522736c2fSopenharmony_ci        return SwitchExtension(userId, info);
80622736c2fSopenharmony_ci    }
80722736c2fSopenharmony_ci    return SwitchSubType(userId, info);
80822736c2fSopenharmony_ci}
80922736c2fSopenharmony_ci
81022736c2fSopenharmony_ci// Switch the current InputMethodExtension to the new InputMethodExtension
81122736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchExtension(int32_t userId, const std::shared_ptr<ImeInfo> &info)
81222736c2fSopenharmony_ci{
81322736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
81422736c2fSopenharmony_ci    if (session == nullptr) {
81522736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
81622736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
81722736c2fSopenharmony_ci    }
81822736c2fSopenharmony_ci    std::string targetImeName = info->prop.name + "/" + info->prop.id;
81922736c2fSopenharmony_ci    ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, false });
82022736c2fSopenharmony_ci    ImeNativeCfg targetIme = { targetImeName, info->prop.name, info->subProp.id, info->prop.id };
82122736c2fSopenharmony_ci    if (!session->StartIme(std::make_shared<ImeNativeCfg>(targetIme))) {
82222736c2fSopenharmony_ci        IMSA_HILOGE("start input method failed!");
82322736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_START_FAILED;
82422736c2fSopenharmony_ci    }
82522736c2fSopenharmony_ci    session->NotifyImeChangeToClients(info->prop, info->subProp);
82622736c2fSopenharmony_ci    GetValidSubtype("", info);
82722736c2fSopenharmony_ci    session->SwitchSubtype(info->subProp);
82822736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
82922736c2fSopenharmony_ci}
83022736c2fSopenharmony_ci
83122736c2fSopenharmony_ci// Inform current InputMethodExtension to switch subtype
83222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchSubType(int32_t userId, const std::shared_ptr<ImeInfo> &info)
83322736c2fSopenharmony_ci{
83422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
83522736c2fSopenharmony_ci    if (session == nullptr) {
83622736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
83722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
83822736c2fSopenharmony_ci    }
83922736c2fSopenharmony_ci    auto ret = session->SwitchSubtype(info->subProp);
84022736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
84122736c2fSopenharmony_ci        IMSA_HILOGE("failed to inform ime to switch subtype, ret: %{public}d!", ret);
84222736c2fSopenharmony_ci        return ret;
84322736c2fSopenharmony_ci    }
84422736c2fSopenharmony_ci    auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->imeId;
84522736c2fSopenharmony_ci    ImeCfgManager::GetInstance().ModifyImeCfg({ userId, currentIme, info->subProp.id, false });
84622736c2fSopenharmony_ci    session->NotifyImeChangeToClients(info->prop, info->subProp);
84722736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
84822736c2fSopenharmony_ci}
84922736c2fSopenharmony_ci
85022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchInputType(int32_t userId, const SwitchInfo &switchInfo)
85122736c2fSopenharmony_ci{
85222736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
85322736c2fSopenharmony_ci    if (session == nullptr) {
85422736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
85522736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
85622736c2fSopenharmony_ci    }
85722736c2fSopenharmony_ci    auto targetImeProperty = ImeInfoInquirer::GetInstance().GetImeProperty(userId, switchInfo.bundleName);
85822736c2fSopenharmony_ci    if (targetImeProperty == nullptr) {
85922736c2fSopenharmony_ci        IMSA_HILOGE("GetImeProperty [%{public}d, %{public}s] failed!", userId, switchInfo.bundleName.c_str());
86022736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
86122736c2fSopenharmony_ci    }
86222736c2fSopenharmony_ci    std::string targetName = switchInfo.bundleName + "/" + targetImeProperty->id;
86322736c2fSopenharmony_ci    ImeNativeCfg targetIme = { targetName, switchInfo.bundleName, switchInfo.subName, targetImeProperty->id };
86422736c2fSopenharmony_ci    InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName });
86522736c2fSopenharmony_ci    if (!session->StartIme(std::make_shared<ImeNativeCfg>(targetIme))) {
86622736c2fSopenharmony_ci        IMSA_HILOGE("start input method failed!");
86722736c2fSopenharmony_ci        InputTypeManager::GetInstance().Set(false);
86822736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_START_FAILED;
86922736c2fSopenharmony_ci    }
87022736c2fSopenharmony_ci    int32_t ret = session->SwitchSubtype({ .name = switchInfo.bundleName, .id = switchInfo.subName });
87122736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
87222736c2fSopenharmony_ci        InputTypeManager::GetInstance().Set(false);
87322736c2fSopenharmony_ci        IMSA_HILOGE("switch subtype failed!");
87422736c2fSopenharmony_ci        return ret;
87522736c2fSopenharmony_ci    }
87622736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
87722736c2fSopenharmony_ci}
87822736c2fSopenharmony_ci
87922736c2fSopenharmony_ci// Deprecated because of no permission check, kept for compatibility
88022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::HideCurrentInputDeprecated()
88122736c2fSopenharmony_ci{
88222736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
88322736c2fSopenharmony_ci    int32_t userId = GetCallingUserId();
88422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
88522736c2fSopenharmony_ci    if (session == nullptr) {
88622736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
88722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
88822736c2fSopenharmony_ci    }
88922736c2fSopenharmony_ci    if (!identityChecker_->IsBroker(tokenId)) {
89022736c2fSopenharmony_ci        if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
89122736c2fSopenharmony_ci            return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
89222736c2fSopenharmony_ci        }
89322736c2fSopenharmony_ci    }
89422736c2fSopenharmony_ci    return session->OnHideCurrentInput();
89522736c2fSopenharmony_ci}
89622736c2fSopenharmony_ci
89722736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ShowCurrentInputDeprecated()
89822736c2fSopenharmony_ci{
89922736c2fSopenharmony_ci    AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
90022736c2fSopenharmony_ci    int32_t userId = GetCallingUserId();
90122736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
90222736c2fSopenharmony_ci    if (session == nullptr) {
90322736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
90422736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
90522736c2fSopenharmony_ci    }
90622736c2fSopenharmony_ci    if (!identityChecker_->IsBroker(tokenId)) {
90722736c2fSopenharmony_ci        if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
90822736c2fSopenharmony_ci            return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
90922736c2fSopenharmony_ci        }
91022736c2fSopenharmony_ci    }
91122736c2fSopenharmony_ci    return session->OnShowCurrentInput();
91222736c2fSopenharmony_ci}
91322736c2fSopenharmony_ci
91422736c2fSopenharmony_cistd::shared_ptr<Property> InputMethodSystemAbility::GetCurrentInputMethod()
91522736c2fSopenharmony_ci{
91622736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().GetCurrentInputMethod(GetCallingUserId());
91722736c2fSopenharmony_ci}
91822736c2fSopenharmony_ci
91922736c2fSopenharmony_cibool InputMethodSystemAbility::IsDefaultImeSet()
92022736c2fSopenharmony_ci{
92122736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().IsDefaultImeSet(GetCallingUserId());
92222736c2fSopenharmony_ci}
92322736c2fSopenharmony_ci
92422736c2fSopenharmony_cistd::shared_ptr<SubProperty> InputMethodSystemAbility::GetCurrentInputMethodSubtype()
92522736c2fSopenharmony_ci{
92622736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().GetCurrentSubtype(GetCallingUserId());
92722736c2fSopenharmony_ci}
92822736c2fSopenharmony_ci
92922736c2fSopenharmony_ciint32_t InputMethodSystemAbility::GetDefaultInputMethod(std::shared_ptr<Property> &prop, bool isBrief)
93022736c2fSopenharmony_ci{
93122736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().GetDefaultInputMethod(GetCallingUserId(), prop, isBrief);
93222736c2fSopenharmony_ci}
93322736c2fSopenharmony_ci
93422736c2fSopenharmony_ciint32_t InputMethodSystemAbility::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
93522736c2fSopenharmony_ci{
93622736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().GetInputMethodConfig(GetCallingUserId(), inputMethodConfig);
93722736c2fSopenharmony_ci}
93822736c2fSopenharmony_ci
93922736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ListInputMethod(InputMethodStatus status, std::vector<Property> &props)
94022736c2fSopenharmony_ci{
94122736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().ListInputMethod(GetCallingUserId(), status, props, enableImeOn_.load());
94222736c2fSopenharmony_ci}
94322736c2fSopenharmony_ci
94422736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
94522736c2fSopenharmony_ci{
94622736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().ListCurrentInputMethodSubtype(GetCallingUserId(), subProps);
94722736c2fSopenharmony_ci}
94822736c2fSopenharmony_ci
94922736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ListInputMethodSubtype(const std::string &bundleName,
95022736c2fSopenharmony_ci    std::vector<SubProperty> &subProps)
95122736c2fSopenharmony_ci{
95222736c2fSopenharmony_ci    return ImeInfoInquirer::GetInstance().ListInputMethodSubtype(GetCallingUserId(), bundleName, subProps);
95322736c2fSopenharmony_ci}
95422736c2fSopenharmony_ci
95522736c2fSopenharmony_ci/**
95622736c2fSopenharmony_ci * Work Thread of input method management service
95722736c2fSopenharmony_ci * \n Remote commands which may change the state or data in the service will be handled sequentially in this thread.
95822736c2fSopenharmony_ci */
95922736c2fSopenharmony_civoid InputMethodSystemAbility::WorkThread()
96022736c2fSopenharmony_ci{
96122736c2fSopenharmony_ci    pthread_setname_np(pthread_self(), "OS_IMSAWorkThread");
96222736c2fSopenharmony_ci    while (!stop_) {
96322736c2fSopenharmony_ci        Message *msg = MessageHandler::Instance()->GetMessage();
96422736c2fSopenharmony_ci        switch (msg->msgId_) {
96522736c2fSopenharmony_ci            case MSG_ID_USER_START: {
96622736c2fSopenharmony_ci                OnUserStarted(msg);
96722736c2fSopenharmony_ci                break;
96822736c2fSopenharmony_ci            }
96922736c2fSopenharmony_ci            case MSG_ID_USER_REMOVED: {
97022736c2fSopenharmony_ci                OnUserRemoved(msg);
97122736c2fSopenharmony_ci                break;
97222736c2fSopenharmony_ci            }
97322736c2fSopenharmony_ci            case MSG_ID_USER_STOP: {
97422736c2fSopenharmony_ci                OnUserStop(msg);
97522736c2fSopenharmony_ci                break;
97622736c2fSopenharmony_ci            }
97722736c2fSopenharmony_ci            case MSG_ID_HIDE_KEYBOARD_SELF: {
97822736c2fSopenharmony_ci                OnHideKeyboardSelf(msg);
97922736c2fSopenharmony_ci                break;
98022736c2fSopenharmony_ci            }
98122736c2fSopenharmony_ci            case MSG_ID_BUNDLE_SCAN_FINISHED: {
98222736c2fSopenharmony_ci                RegisterDataShareObserver();
98322736c2fSopenharmony_ci                FullImeInfoManager::GetInstance().Init();
98422736c2fSopenharmony_ci                break;
98522736c2fSopenharmony_ci            }
98622736c2fSopenharmony_ci            case MSG_ID_PACKAGE_ADDED:
98722736c2fSopenharmony_ci            case MSG_ID_PACKAGE_CHANGED:
98822736c2fSopenharmony_ci            case MSG_ID_PACKAGE_REMOVED: {
98922736c2fSopenharmony_ci                HandlePackageEvent(msg);
99022736c2fSopenharmony_ci                break;
99122736c2fSopenharmony_ci            }
99222736c2fSopenharmony_ci            case MSG_ID_SYS_LANGUAGE_CHANGED: {
99322736c2fSopenharmony_ci                FullImeInfoManager::GetInstance().Update();
99422736c2fSopenharmony_ci                break;
99522736c2fSopenharmony_ci            }
99622736c2fSopenharmony_ci            case MSG_ID_BOOT_COMPLETED:
99722736c2fSopenharmony_ci            case MSG_ID_OS_ACCOUNT_STARTED: {
99822736c2fSopenharmony_ci                FullImeInfoManager::GetInstance().Init();
99922736c2fSopenharmony_ci                break;
100022736c2fSopenharmony_ci            }
100122736c2fSopenharmony_ci            default: {
100222736c2fSopenharmony_ci                IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
100322736c2fSopenharmony_ci                break;
100422736c2fSopenharmony_ci            }
100522736c2fSopenharmony_ci        }
100622736c2fSopenharmony_ci        delete msg;
100722736c2fSopenharmony_ci    }
100822736c2fSopenharmony_ci}
100922736c2fSopenharmony_ci
101022736c2fSopenharmony_ci/**
101122736c2fSopenharmony_ci * Called when a user is started. (EVENT_USER_STARTED is received)
101222736c2fSopenharmony_ci * \n Run in work thread of input method management service
101322736c2fSopenharmony_ci * \param msg the parameters are saved in msg->msgContent_
101422736c2fSopenharmony_ci * \return ErrorCode
101522736c2fSopenharmony_ci */
101622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnUserStarted(const Message *msg)
101722736c2fSopenharmony_ci{
101822736c2fSopenharmony_ci    if (msg->msgContent_ == nullptr) {
101922736c2fSopenharmony_ci        IMSA_HILOGE("msgContent_ is nullptr!");
102022736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
102122736c2fSopenharmony_ci    }
102222736c2fSopenharmony_ci    auto newUserId = msg->msgContent_->ReadInt32();
102322736c2fSopenharmony_ci    FullImeInfoManager::GetInstance().Add(newUserId);
102422736c2fSopenharmony_ci    // if scb enable, deal when receive wmsConnected.
102522736c2fSopenharmony_ci    if (isScbEnable_.load()) {
102622736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
102722736c2fSopenharmony_ci    }
102822736c2fSopenharmony_ci    if (newUserId == userId_) {
102922736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
103022736c2fSopenharmony_ci    }
103122736c2fSopenharmony_ci    HandleUserSwitched(newUserId);
103222736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
103322736c2fSopenharmony_ci}
103422736c2fSopenharmony_ci
103522736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnUserRemoved(const Message *msg)
103622736c2fSopenharmony_ci{
103722736c2fSopenharmony_ci    if (msg == nullptr || msg->msgContent_ == nullptr) {
103822736c2fSopenharmony_ci        IMSA_HILOGE("Aborted! Message is nullptr!");
103922736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
104022736c2fSopenharmony_ci    }
104122736c2fSopenharmony_ci    auto userId = msg->msgContent_->ReadInt32();
104222736c2fSopenharmony_ci    IMSA_HILOGI("start: %{public}d", userId);
104322736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
104422736c2fSopenharmony_ci    if (session != nullptr) {
104522736c2fSopenharmony_ci        session->StopCurrentIme();
104622736c2fSopenharmony_ci        UserSessionManager::GetInstance().RemoveUserSession(userId);
104722736c2fSopenharmony_ci    }
104822736c2fSopenharmony_ci    ImeCfgManager::GetInstance().DeleteImeCfg(userId);
104922736c2fSopenharmony_ci    FullImeInfoManager::GetInstance().Delete(userId);
105022736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
105122736c2fSopenharmony_ci}
105222736c2fSopenharmony_ci
105322736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnUserStop(const Message *msg)
105422736c2fSopenharmony_ci{
105522736c2fSopenharmony_ci    if (msg == nullptr || msg->msgContent_ == nullptr) {
105622736c2fSopenharmony_ci        IMSA_HILOGE("Aborted! Message is nullptr!");
105722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
105822736c2fSopenharmony_ci    }
105922736c2fSopenharmony_ci    auto userId = msg->msgContent_->ReadInt32();
106022736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
106122736c2fSopenharmony_ci    if (session == nullptr) {
106222736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
106322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
106422736c2fSopenharmony_ci    }
106522736c2fSopenharmony_ci    session->StopCurrentIme();
106622736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
106722736c2fSopenharmony_ci}
106822736c2fSopenharmony_ci
106922736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnHideKeyboardSelf(const Message *msg)
107022736c2fSopenharmony_ci{
107122736c2fSopenharmony_ci    if (msg == nullptr || msg->msgContent_ == nullptr) {
107222736c2fSopenharmony_ci        IMSA_HILOGE("Aborted! Message is nullptr!");
107322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
107422736c2fSopenharmony_ci    }
107522736c2fSopenharmony_ci    auto userId = msg->msgContent_->ReadInt32();
107622736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
107722736c2fSopenharmony_ci    if (session == nullptr) {
107822736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
107922736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
108022736c2fSopenharmony_ci    }
108122736c2fSopenharmony_ci    session->OnHideSoftKeyBoardSelf();
108222736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
108322736c2fSopenharmony_ci}
108422736c2fSopenharmony_ci
108522736c2fSopenharmony_ciint32_t InputMethodSystemAbility::HandlePackageEvent(const Message *msg)
108622736c2fSopenharmony_ci{
108722736c2fSopenharmony_ci    MessageParcel *data = msg->msgContent_;
108822736c2fSopenharmony_ci    if (data == nullptr) {
108922736c2fSopenharmony_ci        IMSA_HILOGD("data is nullptr");
109022736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
109122736c2fSopenharmony_ci    }
109222736c2fSopenharmony_ci    int32_t userId = 0;
109322736c2fSopenharmony_ci    std::string packageName;
109422736c2fSopenharmony_ci    if (!ITypesUtil::Unmarshal(*data, userId, packageName)) {
109522736c2fSopenharmony_ci        IMSA_HILOGE("Failed to read message parcel!");
109622736c2fSopenharmony_ci        return ErrorCode::ERROR_EX_PARCELABLE;
109722736c2fSopenharmony_ci    }
109822736c2fSopenharmony_ci    if (msg->msgId_ == MSG_ID_PACKAGE_CHANGED) {
109922736c2fSopenharmony_ci        return FullImeInfoManager::GetInstance().Update(userId, packageName);
110022736c2fSopenharmony_ci    }
110122736c2fSopenharmony_ci    if (msg->msgId_ == MSG_ID_PACKAGE_ADDED) {
110222736c2fSopenharmony_ci        return FullImeInfoManager::GetInstance().Add(userId, packageName);
110322736c2fSopenharmony_ci    }
110422736c2fSopenharmony_ci    if (msg->msgId_ == MSG_ID_PACKAGE_REMOVED) {
110522736c2fSopenharmony_ci        return OnPackageRemoved(userId, packageName);
110622736c2fSopenharmony_ci    }
110722736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
110822736c2fSopenharmony_ci}
110922736c2fSopenharmony_ci
111022736c2fSopenharmony_ci/**
111122736c2fSopenharmony_ci *  Called when a package is removed.
111222736c2fSopenharmony_ci *  \n Run in work thread of input method management service
111322736c2fSopenharmony_ci *  \param msg the parameters are saved in msg->msgContent_
111422736c2fSopenharmony_ci *  \return ErrorCode::NO_ERROR
111522736c2fSopenharmony_ci *  \return ErrorCode::ERROR_USER_NOT_UNLOCKED user not unlocked
111622736c2fSopenharmony_ci *  \return ErrorCode::ERROR_BAD_PARAMETERS bad parameter
111722736c2fSopenharmony_ci */
111822736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnPackageRemoved(int32_t userId, const std::string &packageName)
111922736c2fSopenharmony_ci{
112022736c2fSopenharmony_ci    FullImeInfoManager::GetInstance().Delete(userId, packageName);
112122736c2fSopenharmony_ci    // if the app that doesn't belong to current user is removed, ignore it
112222736c2fSopenharmony_ci    if (userId != userId_) {
112322736c2fSopenharmony_ci        IMSA_HILOGD("userId: %{public}d, currentUserId: %{public}d.", userId, userId_);
112422736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
112522736c2fSopenharmony_ci    }
112622736c2fSopenharmony_ci    auto currentImeBundle = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
112722736c2fSopenharmony_ci    if (packageName == currentImeBundle) {
112822736c2fSopenharmony_ci        // Switch to the default ime
112922736c2fSopenharmony_ci        IMSA_HILOGI("user[%{public}d] ime: %{public}s is uninstalled.", userId, packageName.c_str());
113022736c2fSopenharmony_ci        auto info = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
113122736c2fSopenharmony_ci        if (info == nullptr) {
113222736c2fSopenharmony_ci            return ErrorCode::ERROR_PERSIST_CONFIG;
113322736c2fSopenharmony_ci        }
113422736c2fSopenharmony_ci        int32_t ret = SwitchExtension(userId, info);
113522736c2fSopenharmony_ci        IMSA_HILOGI("switch ret: %{public}d", ret);
113622736c2fSopenharmony_ci    }
113722736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
113822736c2fSopenharmony_ci}
113922736c2fSopenharmony_ci
114022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::OnDisplayOptionalInputMethod()
114122736c2fSopenharmony_ci{
114222736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility::OnDisplayOptionalInputMethod start.");
114322736c2fSopenharmony_ci    AAFwk::Want want;
114422736c2fSopenharmony_ci    want.SetAction(SELECT_DIALOG_ACTION);
114522736c2fSopenharmony_ci    want.SetElementName(SELECT_DIALOG_HAP, SELECT_DIALOG_ABILITY);
114622736c2fSopenharmony_ci    int32_t ret = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
114722736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR && ret != START_SERVICE_ABILITY_ACTIVATING) {
114822736c2fSopenharmony_ci        IMSA_HILOGE("start InputMethod ability failed, err: %{public}d", ret);
114922736c2fSopenharmony_ci        return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
115022736c2fSopenharmony_ci    }
115122736c2fSopenharmony_ci    IMSA_HILOGI("start InputMethod ability success.");
115222736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
115322736c2fSopenharmony_ci}
115422736c2fSopenharmony_ci
115522736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state)
115622736c2fSopenharmony_ci{
115722736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility::SwitchByCombinationKey start.");
115822736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
115922736c2fSopenharmony_ci    if (session == nullptr) {
116022736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId_);
116122736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
116222736c2fSopenharmony_ci    }
116322736c2fSopenharmony_ci    if (session->IsProxyImeEnable()) {
116422736c2fSopenharmony_ci        IMSA_HILOGI("proxy enable, not switch.");
116522736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
116622736c2fSopenharmony_ci    }
116722736c2fSopenharmony_ci    if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_MODE, state)) {
116822736c2fSopenharmony_ci        IMSA_HILOGI("switch mode.");
116922736c2fSopenharmony_ci        return SwitchMode();
117022736c2fSopenharmony_ci    }
117122736c2fSopenharmony_ci    if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_LANGUAGE, state)) {
117222736c2fSopenharmony_ci        IMSA_HILOGI("switch language.");
117322736c2fSopenharmony_ci        return SwitchLanguage();
117422736c2fSopenharmony_ci    }
117522736c2fSopenharmony_ci    bool isScreenLocked = false;
117622736c2fSopenharmony_ci#ifdef IMF_SCREENLOCK_MGR_ENABLE
117722736c2fSopenharmony_ci    if (ScreenLock::ScreenLockManager::GetInstance()->IsScreenLocked()) {
117822736c2fSopenharmony_ci        IMSA_HILOGI("isScreenLocked  now.");
117922736c2fSopenharmony_ci        isScreenLocked = true;
118022736c2fSopenharmony_ci    }
118122736c2fSopenharmony_ci#endif
118222736c2fSopenharmony_ci    if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_IME, state) && !isScreenLocked) {
118322736c2fSopenharmony_ci        IMSA_HILOGI("switch ime.");
118422736c2fSopenharmony_ci        DealSwitchRequest();
118522736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
118622736c2fSopenharmony_ci    }
118722736c2fSopenharmony_ci    IMSA_HILOGE("keycode is undefined!");
118822736c2fSopenharmony_ci    return ErrorCode::ERROR_EX_UNSUPPORTED_OPERATION;
118922736c2fSopenharmony_ci}
119022736c2fSopenharmony_ci
119122736c2fSopenharmony_civoid InputMethodSystemAbility::DealSecurityChange()
119222736c2fSopenharmony_ci{
119322736c2fSopenharmony_ci    {
119422736c2fSopenharmony_ci        std::lock_guard<std::mutex> lock(modeChangeMutex_);
119522736c2fSopenharmony_ci        if (isChangeHandling_) {
119622736c2fSopenharmony_ci            IMSA_HILOGI("already has mode change task.");
119722736c2fSopenharmony_ci            hasPendingChanges_ = true;
119822736c2fSopenharmony_ci            return;
119922736c2fSopenharmony_ci        } else {
120022736c2fSopenharmony_ci            isChangeHandling_ = true;
120122736c2fSopenharmony_ci            hasPendingChanges_ = true;
120222736c2fSopenharmony_ci        }
120322736c2fSopenharmony_ci    }
120422736c2fSopenharmony_ci    auto changeTask = [this]() {
120522736c2fSopenharmony_ci        pthread_setname_np(pthread_self(), "SecurityChange");
120622736c2fSopenharmony_ci        auto checkChangeCount = [this]() {
120722736c2fSopenharmony_ci            std::lock_guard<std::mutex> lock(modeChangeMutex_);
120822736c2fSopenharmony_ci            if (hasPendingChanges_) {
120922736c2fSopenharmony_ci                return true;
121022736c2fSopenharmony_ci            }
121122736c2fSopenharmony_ci            isChangeHandling_ = false;
121222736c2fSopenharmony_ci            return false;
121322736c2fSopenharmony_ci        };
121422736c2fSopenharmony_ci        do {
121522736c2fSopenharmony_ci            OnSecurityModeChange();
121622736c2fSopenharmony_ci        } while (checkChangeCount());
121722736c2fSopenharmony_ci    };
121822736c2fSopenharmony_ci    std::thread(changeTask).detach();
121922736c2fSopenharmony_ci}
122022736c2fSopenharmony_ci
122122736c2fSopenharmony_civoid InputMethodSystemAbility::DealSwitchRequest()
122222736c2fSopenharmony_ci{
122322736c2fSopenharmony_ci    {
122422736c2fSopenharmony_ci        std::lock_guard<std::mutex> lock(switchImeMutex_);
122522736c2fSopenharmony_ci        // 0 means current swich ime task count.
122622736c2fSopenharmony_ci        if (switchTaskExecuting_.load()) {
122722736c2fSopenharmony_ci            IMSA_HILOGI("already has switch ime task.");
122822736c2fSopenharmony_ci            ++targetSwitchCount_;
122922736c2fSopenharmony_ci            return;
123022736c2fSopenharmony_ci        } else {
123122736c2fSopenharmony_ci            switchTaskExecuting_.store(true);
123222736c2fSopenharmony_ci            ++targetSwitchCount_;
123322736c2fSopenharmony_ci        }
123422736c2fSopenharmony_ci    }
123522736c2fSopenharmony_ci    auto switchTask = [this]() {
123622736c2fSopenharmony_ci        auto checkSwitchCount = [this]() {
123722736c2fSopenharmony_ci            std::lock_guard<std::mutex> lock(switchImeMutex_);
123822736c2fSopenharmony_ci            if (targetSwitchCount_ > 0) {
123922736c2fSopenharmony_ci                return true;
124022736c2fSopenharmony_ci            }
124122736c2fSopenharmony_ci            switchTaskExecuting_.store(false);
124222736c2fSopenharmony_ci            return false;
124322736c2fSopenharmony_ci        };
124422736c2fSopenharmony_ci        do {
124522736c2fSopenharmony_ci            SwitchType();
124622736c2fSopenharmony_ci        } while (checkSwitchCount());
124722736c2fSopenharmony_ci    };
124822736c2fSopenharmony_ci    // 0 means delay time is 0.
124922736c2fSopenharmony_ci    serviceHandler_->PostTask(switchTask, "SwitchImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
125022736c2fSopenharmony_ci}
125122736c2fSopenharmony_ci
125222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchMode()
125322736c2fSopenharmony_ci{
125422736c2fSopenharmony_ci    auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
125522736c2fSopenharmony_ci    auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
125622736c2fSopenharmony_ci    auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
125722736c2fSopenharmony_ci    if (info == nullptr) {
125822736c2fSopenharmony_ci        IMSA_HILOGE("current ime is abnormal!");
125922736c2fSopenharmony_ci        return ErrorCode::ERROR_BAD_PARAMETERS;
126022736c2fSopenharmony_ci    }
126122736c2fSopenharmony_ci    if (info->isNewIme) {
126222736c2fSopenharmony_ci        IMSA_HILOGD("the switching operation is handed over to ime.");
126322736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
126422736c2fSopenharmony_ci    }
126522736c2fSopenharmony_ci    auto condition = info->subProp.mode == "upper" ? Condition::LOWER : Condition::UPPER;
126622736c2fSopenharmony_ci    auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
126722736c2fSopenharmony_ci    if (target == nullptr) {
126822736c2fSopenharmony_ci        IMSA_HILOGE("target is empty!");
126922736c2fSopenharmony_ci        return ErrorCode::ERROR_BAD_PARAMETERS;
127022736c2fSopenharmony_ci    }
127122736c2fSopenharmony_ci    SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
127222736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
127322736c2fSopenharmony_ci    if (session == nullptr) {
127422736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId_);
127522736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
127622736c2fSopenharmony_ci    }
127722736c2fSopenharmony_ci    session->GetSwitchQueue().Push(switchInfo);
127822736c2fSopenharmony_ci    return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
127922736c2fSopenharmony_ci}
128022736c2fSopenharmony_ci
128122736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchLanguage()
128222736c2fSopenharmony_ci{
128322736c2fSopenharmony_ci    auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
128422736c2fSopenharmony_ci    auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
128522736c2fSopenharmony_ci    auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
128622736c2fSopenharmony_ci    if (info == nullptr) {
128722736c2fSopenharmony_ci        IMSA_HILOGE("current ime is abnormal!");
128822736c2fSopenharmony_ci        return ErrorCode::ERROR_BAD_PARAMETERS;
128922736c2fSopenharmony_ci    }
129022736c2fSopenharmony_ci    if (info->isNewIme) {
129122736c2fSopenharmony_ci        IMSA_HILOGD("the switching operation is handed over to ime.");
129222736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
129322736c2fSopenharmony_ci    }
129422736c2fSopenharmony_ci    if (info->subProp.language != "chinese" && info->subProp.language != "english") {
129522736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
129622736c2fSopenharmony_ci    }
129722736c2fSopenharmony_ci    auto condition = info->subProp.language == "chinese" ? Condition::ENGLISH : Condition::CHINESE;
129822736c2fSopenharmony_ci    auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
129922736c2fSopenharmony_ci    if (target == nullptr) {
130022736c2fSopenharmony_ci        IMSA_HILOGE("target is empty!");
130122736c2fSopenharmony_ci        return ErrorCode::ERROR_BAD_PARAMETERS;
130222736c2fSopenharmony_ci    }
130322736c2fSopenharmony_ci    SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
130422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
130522736c2fSopenharmony_ci    if (session == nullptr) {
130622736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId_);
130722736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
130822736c2fSopenharmony_ci    }
130922736c2fSopenharmony_ci    session->GetSwitchQueue().Push(switchInfo);
131022736c2fSopenharmony_ci    return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
131122736c2fSopenharmony_ci}
131222736c2fSopenharmony_ci
131322736c2fSopenharmony_ciint32_t InputMethodSystemAbility::SwitchType()
131422736c2fSopenharmony_ci{
131522736c2fSopenharmony_ci    SwitchInfo switchInfo = { std::chrono::system_clock::now(), "", "" };
131622736c2fSopenharmony_ci    uint32_t cacheCount = 0;
131722736c2fSopenharmony_ci    {
131822736c2fSopenharmony_ci        std::lock_guard<std::mutex> lock(switchImeMutex_);
131922736c2fSopenharmony_ci        cacheCount = targetSwitchCount_.exchange(0);
132022736c2fSopenharmony_ci    }
132122736c2fSopenharmony_ci    int32_t ret =
132222736c2fSopenharmony_ci        ImeInfoInquirer::GetInstance().GetSwitchInfoBySwitchCount(switchInfo, userId_, enableImeOn_.load(), cacheCount);
132322736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
132422736c2fSopenharmony_ci        IMSA_HILOGE("get next SwitchInfo failed, stop switching ime.");
132522736c2fSopenharmony_ci        return ret;
132622736c2fSopenharmony_ci    }
132722736c2fSopenharmony_ci    IMSA_HILOGD("switch to: %{public}s.", switchInfo.bundleName.c_str());
132822736c2fSopenharmony_ci    switchInfo.timestamp = std::chrono::system_clock::now();
132922736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
133022736c2fSopenharmony_ci    if (session == nullptr) {
133122736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId_);
133222736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
133322736c2fSopenharmony_ci    }
133422736c2fSopenharmony_ci    session->GetSwitchQueue().Push(switchInfo);
133522736c2fSopenharmony_ci    return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
133622736c2fSopenharmony_ci}
133722736c2fSopenharmony_ci
133822736c2fSopenharmony_civoid InputMethodSystemAbility::InitMonitors()
133922736c2fSopenharmony_ci{
134022736c2fSopenharmony_ci    int32_t ret = InitAccountMonitor();
134122736c2fSopenharmony_ci    IMSA_HILOGI("init account monitor, ret: %{public}d.", ret);
134222736c2fSopenharmony_ci    SubscribeCommonEvent();
134322736c2fSopenharmony_ci    ret = InitMemMgrMonitor();
134422736c2fSopenharmony_ci    IMSA_HILOGI("init MemMgr monitor, ret: %{public}d.", ret);
134522736c2fSopenharmony_ci    ret = InitKeyEventMonitor();
134622736c2fSopenharmony_ci    IMSA_HILOGI("init KeyEvent monitor, ret: %{public}d.", ret);
134722736c2fSopenharmony_ci    ret = InitWmsMonitor();
134822736c2fSopenharmony_ci    IMSA_HILOGI("init wms monitor, ret: %{public}d.", ret);
134922736c2fSopenharmony_ci    InitSystemLanguageMonitor();
135022736c2fSopenharmony_ci    if (ImeInfoInquirer::GetInstance().IsEnableInputMethod()) {
135122736c2fSopenharmony_ci        IMSA_HILOGW("Enter enable mode.");
135222736c2fSopenharmony_ci        EnableImeDataParser::GetInstance()->Initialize(userId_);
135322736c2fSopenharmony_ci        enableImeOn_.store(true);
135422736c2fSopenharmony_ci    }
135522736c2fSopenharmony_ci    if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
135622736c2fSopenharmony_ci        IMSA_HILOGW("Enter security mode.");
135722736c2fSopenharmony_ci        enableSecurityMode_.store(true);
135822736c2fSopenharmony_ci    }
135922736c2fSopenharmony_ci    RegisterDataShareObserver();
136022736c2fSopenharmony_ci}
136122736c2fSopenharmony_ci
136222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::RegisterDataShareObserver()
136322736c2fSopenharmony_ci{
136422736c2fSopenharmony_ci    IMSA_HILOGD("start.");
136522736c2fSopenharmony_ci    if (ImeInfoInquirer::GetInstance().IsEnableInputMethod()) {
136622736c2fSopenharmony_ci        RegisterEnableImeObserver();
136722736c2fSopenharmony_ci    }
136822736c2fSopenharmony_ci    if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
136922736c2fSopenharmony_ci        RegisterSecurityModeObserver();
137022736c2fSopenharmony_ci    }
137122736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
137222736c2fSopenharmony_ci}
137322736c2fSopenharmony_ci
137422736c2fSopenharmony_ciint32_t InputMethodSystemAbility::InitAccountMonitor()
137522736c2fSopenharmony_ci{
137622736c2fSopenharmony_ci    IMSA_HILOGI("InputMethodSystemAbility::InitAccountMonitor start.");
137722736c2fSopenharmony_ci    return ImCommonEventManager::GetInstance()->SubscribeAccountManagerService([this]() { HandleOsAccountStarted(); });
137822736c2fSopenharmony_ci}
137922736c2fSopenharmony_ci
138022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::InitKeyEventMonitor()
138122736c2fSopenharmony_ci{
138222736c2fSopenharmony_ci    IMSA_HILOGI("InputMethodSystemAbility::InitKeyEventMonitor start.");
138322736c2fSopenharmony_ci    bool ret = ImCommonEventManager::GetInstance()->SubscribeKeyboardEvent(
138422736c2fSopenharmony_ci        [this](uint32_t keyCode) { return SwitchByCombinationKey(keyCode); });
138522736c2fSopenharmony_ci    return ret ? ErrorCode::NO_ERROR : ErrorCode::ERROR_SERVICE_START_FAILED;
138622736c2fSopenharmony_ci}
138722736c2fSopenharmony_ci
138822736c2fSopenharmony_cibool InputMethodSystemAbility::InitWmsMonitor()
138922736c2fSopenharmony_ci{
139022736c2fSopenharmony_ci    return ImCommonEventManager::GetInstance()->SubscribeWindowManagerService([this]() { HandleWmsStarted(); });
139122736c2fSopenharmony_ci}
139222736c2fSopenharmony_ci
139322736c2fSopenharmony_cibool InputMethodSystemAbility::InitMemMgrMonitor()
139422736c2fSopenharmony_ci{
139522736c2fSopenharmony_ci    return ImCommonEventManager::GetInstance()->SubscribeMemMgrService([this]() { HandleMemStarted(); });
139622736c2fSopenharmony_ci}
139722736c2fSopenharmony_ci
139822736c2fSopenharmony_civoid InputMethodSystemAbility::InitWmsConnectionMonitor()
139922736c2fSopenharmony_ci{
140022736c2fSopenharmony_ci    WmsConnectionMonitorManager::GetInstance().RegisterWMSConnectionChangedListener(
140122736c2fSopenharmony_ci        [this](bool isConnected, int32_t userId, int32_t screenId) {
140222736c2fSopenharmony_ci            isConnected ? HandleWmsConnected(userId, screenId) : HandleWmsDisconnected(userId, screenId);
140322736c2fSopenharmony_ci        });
140422736c2fSopenharmony_ci}
140522736c2fSopenharmony_ci
140622736c2fSopenharmony_civoid InputMethodSystemAbility::InitSystemLanguageMonitor()
140722736c2fSopenharmony_ci{
140822736c2fSopenharmony_ci    SystemLanguageObserver::GetInstance().Watch();
140922736c2fSopenharmony_ci}
141022736c2fSopenharmony_ci
141122736c2fSopenharmony_civoid InputMethodSystemAbility::InitFocusChangedMonitor()
141222736c2fSopenharmony_ci{
141322736c2fSopenharmony_ci    FocusMonitorManager::GetInstance().RegisterFocusChangedListener(
141422736c2fSopenharmony_ci        [this](bool isOnFocused, int32_t pid, int32_t uid) { HandleFocusChanged(isOnFocused, pid, uid); });
141522736c2fSopenharmony_ci}
141622736c2fSopenharmony_ci
141722736c2fSopenharmony_civoid InputMethodSystemAbility::RegisterEnableImeObserver()
141822736c2fSopenharmony_ci{
141922736c2fSopenharmony_ci    int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(EnableImeDataParser::ENABLE_IME,
142022736c2fSopenharmony_ci        [this]() { DatashareCallback(EnableImeDataParser::ENABLE_IME); });
142122736c2fSopenharmony_ci    IMSA_HILOGI("register enable ime observer, ret: %{public}d.", ret);
142222736c2fSopenharmony_ci    ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(EnableImeDataParser::ENABLE_KEYBOARD,
142322736c2fSopenharmony_ci        [this]() { DatashareCallback(EnableImeDataParser::ENABLE_KEYBOARD); });
142422736c2fSopenharmony_ci    IMSA_HILOGI("register enable keyboard observer, ret: %{public}d.", ret);
142522736c2fSopenharmony_ci}
142622736c2fSopenharmony_ci
142722736c2fSopenharmony_civoid InputMethodSystemAbility::RegisterSecurityModeObserver()
142822736c2fSopenharmony_ci{
142922736c2fSopenharmony_ci    int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(SecurityModeParser::SECURITY_MODE,
143022736c2fSopenharmony_ci        [this]() { DatashareCallback(SecurityModeParser::SECURITY_MODE); });
143122736c2fSopenharmony_ci    IMSA_HILOGI("register security mode observer, ret: %{public}d", ret);
143222736c2fSopenharmony_ci}
143322736c2fSopenharmony_ci
143422736c2fSopenharmony_civoid InputMethodSystemAbility::DatashareCallback(const std::string &key)
143522736c2fSopenharmony_ci{
143622736c2fSopenharmony_ci    IMSA_HILOGI("start.");
143722736c2fSopenharmony_ci    if (key == EnableImeDataParser::ENABLE_KEYBOARD || key == EnableImeDataParser::ENABLE_IME) {
143822736c2fSopenharmony_ci        EnableImeDataParser::GetInstance()->OnConfigChanged(userId_, key);
143922736c2fSopenharmony_ci        std::lock_guard<std::mutex> autoLock(checkMutex_);
144022736c2fSopenharmony_ci        SwitchInfo switchInfo;
144122736c2fSopenharmony_ci        if (EnableImeDataParser::GetInstance()->CheckNeedSwitch(key, switchInfo, userId_)) {
144222736c2fSopenharmony_ci            auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
144322736c2fSopenharmony_ci            if (session == nullptr) {
144422736c2fSopenharmony_ci                IMSA_HILOGE("%{public}d session is nullptr!", userId_);
144522736c2fSopenharmony_ci                return;
144622736c2fSopenharmony_ci            }
144722736c2fSopenharmony_ci            switchInfo.timestamp = std::chrono::system_clock::now();
144822736c2fSopenharmony_ci            session->GetSwitchQueue().Push(switchInfo);
144922736c2fSopenharmony_ci            OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
145022736c2fSopenharmony_ci        }
145122736c2fSopenharmony_ci    }
145222736c2fSopenharmony_ci    if (key == SecurityModeParser::SECURITY_MODE) {
145322736c2fSopenharmony_ci        DealSecurityChange();
145422736c2fSopenharmony_ci    }
145522736c2fSopenharmony_ci}
145622736c2fSopenharmony_ci
145722736c2fSopenharmony_civoid InputMethodSystemAbility::OnSecurityModeChange()
145822736c2fSopenharmony_ci{
145922736c2fSopenharmony_ci    {
146022736c2fSopenharmony_ci        std::lock_guard<std::mutex> lock(modeChangeMutex_);
146122736c2fSopenharmony_ci        hasPendingChanges_ = false;
146222736c2fSopenharmony_ci    }
146322736c2fSopenharmony_ci    auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
146422736c2fSopenharmony_ci    auto oldMode = SecurityModeParser::GetInstance()->GetSecurityMode(currentIme->bundleName, userId_);
146522736c2fSopenharmony_ci    SecurityModeParser::GetInstance()->UpdateFullModeList(userId_);
146622736c2fSopenharmony_ci    auto newMode = SecurityModeParser::GetInstance()->GetSecurityMode(currentIme->bundleName, userId_);
146722736c2fSopenharmony_ci    if (oldMode == newMode) {
146822736c2fSopenharmony_ci        IMSA_HILOGD("current ime mode not changed.");
146922736c2fSopenharmony_ci        return;
147022736c2fSopenharmony_ci    }
147122736c2fSopenharmony_ci    IMSA_HILOGI("ime: %{public}s securityMode change to: %{public}d.", currentIme->bundleName.c_str(),
147222736c2fSopenharmony_ci        static_cast<int32_t>(newMode));
147322736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
147422736c2fSopenharmony_ci    if (session == nullptr) {
147522736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId_);
147622736c2fSopenharmony_ci        return;
147722736c2fSopenharmony_ci    }
147822736c2fSopenharmony_ci    session->OnSecurityChange(static_cast<int32_t>(newMode));
147922736c2fSopenharmony_ci    session->AddRestartIme();
148022736c2fSopenharmony_ci}
148122736c2fSopenharmony_ci
148222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::GetSecurityMode(int32_t &security)
148322736c2fSopenharmony_ci{
148422736c2fSopenharmony_ci    IMSA_HILOGD("InputMethodSystemAbility start.");
148522736c2fSopenharmony_ci    if (!enableSecurityMode_.load()) {
148622736c2fSopenharmony_ci        security = static_cast<int32_t>(SecurityMode::FULL);
148722736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
148822736c2fSopenharmony_ci    }
148922736c2fSopenharmony_ci    auto userId = GetCallingUserId();
149022736c2fSopenharmony_ci    auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
149122736c2fSopenharmony_ci    if (bundleName.empty()) {
149222736c2fSopenharmony_ci        bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
149322736c2fSopenharmony_ci        IMSA_HILOGW("%{public}s tokenId not find.", bundleName.c_str());
149422736c2fSopenharmony_ci    }
149522736c2fSopenharmony_ci    SecurityMode mode = SecurityModeParser::GetInstance()->GetSecurityMode(bundleName, userId);
149622736c2fSopenharmony_ci    security = static_cast<int32_t>(mode);
149722736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
149822736c2fSopenharmony_ci}
149922736c2fSopenharmony_ci
150022736c2fSopenharmony_ciint32_t InputMethodSystemAbility::UnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
150122736c2fSopenharmony_ci{
150222736c2fSopenharmony_ci    if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
150322736c2fSopenharmony_ci        IMSA_HILOGE("not native sa!");
150422736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
150522736c2fSopenharmony_ci    }
150622736c2fSopenharmony_ci    auto userId = GetCallingUserId();
150722736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
150822736c2fSopenharmony_ci    if (session == nullptr) {
150922736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
151022736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
151122736c2fSopenharmony_ci    }
151222736c2fSopenharmony_ci    if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) {
151322736c2fSopenharmony_ci        int32_t ret = ErrorCode::NO_ERROR;
151422736c2fSopenharmony_ci        if (session->CheckSecurityMode()) {
151522736c2fSopenharmony_ci            ret = StartInputType(userId, InputType::SECURITY_INPUT);
151622736c2fSopenharmony_ci        } else {
151722736c2fSopenharmony_ci            ret = session->RestoreCurrentIme();
151822736c2fSopenharmony_ci        }
151922736c2fSopenharmony_ci        if (ret != ErrorCode::NO_ERROR) {
152022736c2fSopenharmony_ci            return ret;
152122736c2fSopenharmony_ci        }
152222736c2fSopenharmony_ci    }
152322736c2fSopenharmony_ci    return session->OnUnRegisteredProxyIme(type, core);
152422736c2fSopenharmony_ci}
152522736c2fSopenharmony_ci
152622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::CheckEnableAndSwitchPermission()
152722736c2fSopenharmony_ci{
152822736c2fSopenharmony_ci    if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingFullTokenID())) {
152922736c2fSopenharmony_ci        IMSA_HILOGE("not native sa!");
153022736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
153122736c2fSopenharmony_ci    }
153222736c2fSopenharmony_ci    if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
153322736c2fSopenharmony_ci        IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
153422736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
153522736c2fSopenharmony_ci    }
153622736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
153722736c2fSopenharmony_ci}
153822736c2fSopenharmony_ci
153922736c2fSopenharmony_ciint32_t InputMethodSystemAbility::CheckSwitchPermission(int32_t userId, const SwitchInfo &switchInfo,
154022736c2fSopenharmony_ci    SwitchTrigger trigger)
154122736c2fSopenharmony_ci{
154222736c2fSopenharmony_ci    IMSA_HILOGD("trigger: %{public}d.", static_cast<int32_t>(trigger));
154322736c2fSopenharmony_ci    if (trigger == SwitchTrigger::IMSA) {
154422736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
154522736c2fSopenharmony_ci    }
154622736c2fSopenharmony_ci    if (trigger == SwitchTrigger::NATIVE_SA) {
154722736c2fSopenharmony_ci        return CheckEnableAndSwitchPermission();
154822736c2fSopenharmony_ci    }
154922736c2fSopenharmony_ci    if (trigger == SwitchTrigger::SYSTEM_APP) {
155022736c2fSopenharmony_ci        if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
155122736c2fSopenharmony_ci            IMSA_HILOGE("not system app!");
155222736c2fSopenharmony_ci            return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
155322736c2fSopenharmony_ci        }
155422736c2fSopenharmony_ci        if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
155522736c2fSopenharmony_ci            IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
155622736c2fSopenharmony_ci            return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
155722736c2fSopenharmony_ci        }
155822736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
155922736c2fSopenharmony_ci    }
156022736c2fSopenharmony_ci    if (trigger == SwitchTrigger::CURRENT_IME) {
156122736c2fSopenharmony_ci        // PERMISSION_CONNECT_IME_ABILITY check temporarily reserved for application adaptation, will be deleted soon
156222736c2fSopenharmony_ci        if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
156322736c2fSopenharmony_ci            return ErrorCode::NO_ERROR;
156422736c2fSopenharmony_ci        }
156522736c2fSopenharmony_ci        IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
156622736c2fSopenharmony_ci        // switchInfo.subName.empty() check temporarily reserved for application adaptation, will be deleted soon
156722736c2fSopenharmony_ci        auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
156822736c2fSopenharmony_ci        if (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName) &&
156922736c2fSopenharmony_ci            !switchInfo.subName.empty()) {
157022736c2fSopenharmony_ci            return ErrorCode::NO_ERROR;
157122736c2fSopenharmony_ci        }
157222736c2fSopenharmony_ci        IMSA_HILOGE("not current ime!");
157322736c2fSopenharmony_ci        /* return ErrorCode::ERROR_STATUS_PERMISSION_DENIED temporarily reserved for application adaptation,
157422736c2fSopenharmony_ci        will be replaced by ERROR_NOT_CURRENT_IME soon */
157522736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
157622736c2fSopenharmony_ci    }
157722736c2fSopenharmony_ci    return ErrorCode::ERROR_BAD_PARAMETERS;
157822736c2fSopenharmony_ci}
157922736c2fSopenharmony_ci
158022736c2fSopenharmony_cibool InputMethodSystemAbility::IsStartInputTypePermitted(int32_t userId)
158122736c2fSopenharmony_ci{
158222736c2fSopenharmony_ci    auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
158322736c2fSopenharmony_ci    if (defaultIme == nullptr) {
158422736c2fSopenharmony_ci        IMSA_HILOGE("failed to get default ime!");
158522736c2fSopenharmony_ci        return false;
158622736c2fSopenharmony_ci    }
158722736c2fSopenharmony_ci    auto tokenId = IPCSkeleton::GetCallingTokenID();
158822736c2fSopenharmony_ci    if (identityChecker_->IsBundleNameValid(tokenId, defaultIme->prop.name)) {
158922736c2fSopenharmony_ci        return true;
159022736c2fSopenharmony_ci    }
159122736c2fSopenharmony_ci    if (identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
159222736c2fSopenharmony_ci        return true;
159322736c2fSopenharmony_ci    }
159422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
159522736c2fSopenharmony_ci    if (session == nullptr) {
159622736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
159722736c2fSopenharmony_ci        return false;
159822736c2fSopenharmony_ci    }
159922736c2fSopenharmony_ci    return identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) && session->IsBoundToClient();
160022736c2fSopenharmony_ci}
160122736c2fSopenharmony_ci
160222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::ConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
160322736c2fSopenharmony_ci{
160422736c2fSopenharmony_ci    auto tokenId = IPCSkeleton::GetCallingTokenID();
160522736c2fSopenharmony_ci    if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
160622736c2fSopenharmony_ci        IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
160722736c2fSopenharmony_ci        return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
160822736c2fSopenharmony_ci    }
160922736c2fSopenharmony_ci    auto userId = GetCallingUserId();
161022736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
161122736c2fSopenharmony_ci    if (session == nullptr) {
161222736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
161322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
161422736c2fSopenharmony_ci    }
161522736c2fSopenharmony_ci    return session->OnConnectSystemCmd(channel, agent);
161622736c2fSopenharmony_ci}
161722736c2fSopenharmony_ci
161822736c2fSopenharmony_civoid InputMethodSystemAbility::HandleWmsConnected(int32_t userId, int32_t screenId)
161922736c2fSopenharmony_ci{
162022736c2fSopenharmony_ci    if (userId == userId_) {
162122736c2fSopenharmony_ci        // device boot or scb in foreground reboot
162222736c2fSopenharmony_ci        HandleScbStarted(userId, screenId);
162322736c2fSopenharmony_ci        return;
162422736c2fSopenharmony_ci    }
162522736c2fSopenharmony_ci    // user switched
162622736c2fSopenharmony_ci    HandleUserSwitched(userId);
162722736c2fSopenharmony_ci}
162822736c2fSopenharmony_ci
162922736c2fSopenharmony_civoid InputMethodSystemAbility::HandleScbStarted(int32_t userId, int32_t screenId)
163022736c2fSopenharmony_ci{
163122736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
163222736c2fSopenharmony_ci    if (session == nullptr) {
163322736c2fSopenharmony_ci        UserSessionManager::GetInstance().AddUserSession(userId);
163422736c2fSopenharmony_ci    }
163522736c2fSopenharmony_ci    session = UserSessionManager::GetInstance().GetUserSession(userId);
163622736c2fSopenharmony_ci    if (session == nullptr) {
163722736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
163822736c2fSopenharmony_ci        return;
163922736c2fSopenharmony_ci    }
164022736c2fSopenharmony_ci    session->AddRestartIme();
164122736c2fSopenharmony_ci}
164222736c2fSopenharmony_ci
164322736c2fSopenharmony_civoid InputMethodSystemAbility::HandleUserSwitched(int32_t userId)
164422736c2fSopenharmony_ci{
164522736c2fSopenharmony_ci    UpdateUserInfo(userId);
164622736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
164722736c2fSopenharmony_ci    if (session == nullptr) {
164822736c2fSopenharmony_ci        UserSessionManager::GetInstance().AddUserSession(userId);
164922736c2fSopenharmony_ci    }
165022736c2fSopenharmony_ci    session = UserSessionManager::GetInstance().GetUserSession(userId);
165122736c2fSopenharmony_ci    if (session == nullptr) {
165222736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
165322736c2fSopenharmony_ci        return;
165422736c2fSopenharmony_ci    }
165522736c2fSopenharmony_ci    auto imeData = session->GetReadyImeData(ImeType::IME);
165622736c2fSopenharmony_ci    if (imeData == nullptr && session->IsWmsReady()) {
165722736c2fSopenharmony_ci        session->StartCurrentIme();
165822736c2fSopenharmony_ci    }
165922736c2fSopenharmony_ci}
166022736c2fSopenharmony_ci
166122736c2fSopenharmony_civoid InputMethodSystemAbility::HandleWmsDisconnected(int32_t userId, int32_t screenId)
166222736c2fSopenharmony_ci{
166322736c2fSopenharmony_ci    // clear client
166422736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
166522736c2fSopenharmony_ci    if (session != nullptr) {
166622736c2fSopenharmony_ci        session->RemoveCurrentClient();
166722736c2fSopenharmony_ci    }
166822736c2fSopenharmony_ci
166922736c2fSopenharmony_ci    if (userId == userId_) {
167022736c2fSopenharmony_ci        // user switched or scb in foreground died, not deal
167122736c2fSopenharmony_ci        return;
167222736c2fSopenharmony_ci    }
167322736c2fSopenharmony_ci    // scb in background died, stop ime
167422736c2fSopenharmony_ci    if (session == nullptr) {
167522736c2fSopenharmony_ci        return;
167622736c2fSopenharmony_ci    }
167722736c2fSopenharmony_ci    session->StopCurrentIme();
167822736c2fSopenharmony_ci}
167922736c2fSopenharmony_ci
168022736c2fSopenharmony_civoid InputMethodSystemAbility::HandleWmsStarted()
168122736c2fSopenharmony_ci{
168222736c2fSopenharmony_ci    // singleton, device boot, wms reboot
168322736c2fSopenharmony_ci    IMSA_HILOGI("Wms start.");
168422736c2fSopenharmony_ci    InitFocusChangedMonitor();
168522736c2fSopenharmony_ci    if (isScbEnable_.load()) {
168622736c2fSopenharmony_ci        IMSA_HILOGI("scb enable, register WMS connection listener.");
168722736c2fSopenharmony_ci        InitWmsConnectionMonitor();
168822736c2fSopenharmony_ci        return;
168922736c2fSopenharmony_ci    }
169022736c2fSopenharmony_ci    // clear client
169122736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
169222736c2fSopenharmony_ci    if (session != nullptr) {
169322736c2fSopenharmony_ci        session->RemoveCurrentClient();
169422736c2fSopenharmony_ci    }
169522736c2fSopenharmony_ci    if (session == nullptr) {
169622736c2fSopenharmony_ci        UserSessionManager::GetInstance().AddUserSession(userId_);
169722736c2fSopenharmony_ci    }
169822736c2fSopenharmony_ci    session = UserSessionManager::GetInstance().GetUserSession(userId_);
169922736c2fSopenharmony_ci    if (session == nullptr) {
170022736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId_);
170122736c2fSopenharmony_ci        return;
170222736c2fSopenharmony_ci    }
170322736c2fSopenharmony_ci    session->AddRestartIme();
170422736c2fSopenharmony_ci    StopImeInBackground();
170522736c2fSopenharmony_ci}
170622736c2fSopenharmony_ci
170722736c2fSopenharmony_civoid InputMethodSystemAbility::HandleFocusChanged(bool isFocused, int32_t pid, int32_t uid)
170822736c2fSopenharmony_ci{
170922736c2fSopenharmony_ci    int32_t userId = GetUserId(uid);
171022736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
171122736c2fSopenharmony_ci    if (session == nullptr) {
171222736c2fSopenharmony_ci        IMSA_HILOGE("[%{public}d, %{public}d] session is nullptr!", uid, userId);
171322736c2fSopenharmony_ci        return;
171422736c2fSopenharmony_ci    }
171522736c2fSopenharmony_ci    isFocused ? session->OnFocused(pid, uid) : session->OnUnfocused(pid, uid);
171622736c2fSopenharmony_ci}
171722736c2fSopenharmony_ci
171822736c2fSopenharmony_civoid InputMethodSystemAbility::HandleMemStarted()
171922736c2fSopenharmony_ci{
172022736c2fSopenharmony_ci    // singleton
172122736c2fSopenharmony_ci    IMSA_HILOGI("MemMgr start.");
172222736c2fSopenharmony_ci    Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, INPUT_METHOD_SYSTEM_ABILITY_ID);
172322736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
172422736c2fSopenharmony_ci    if (session == nullptr) {
172522736c2fSopenharmony_ci        UserSessionManager::GetInstance().AddUserSession(userId_);
172622736c2fSopenharmony_ci    }
172722736c2fSopenharmony_ci    session = UserSessionManager::GetInstance().GetUserSession(userId_);
172822736c2fSopenharmony_ci    if (session == nullptr) {
172922736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId_);
173022736c2fSopenharmony_ci        return;
173122736c2fSopenharmony_ci    }
173222736c2fSopenharmony_ci    session->AddRestartIme();
173322736c2fSopenharmony_ci    StopImeInBackground();
173422736c2fSopenharmony_ci}
173522736c2fSopenharmony_ci
173622736c2fSopenharmony_civoid InputMethodSystemAbility::HandleOsAccountStarted()
173722736c2fSopenharmony_ci{
173822736c2fSopenharmony_ci    auto userId = OsAccountAdapter::GetForegroundOsAccountLocalId();
173922736c2fSopenharmony_ci    if (userId_ != userId) {
174022736c2fSopenharmony_ci        UpdateUserInfo(userId);
174122736c2fSopenharmony_ci    }
174222736c2fSopenharmony_ci    Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_OS_ACCOUNT_STARTED, nullptr);
174322736c2fSopenharmony_ci    if (msg == nullptr) {
174422736c2fSopenharmony_ci        return;
174522736c2fSopenharmony_ci    }
174622736c2fSopenharmony_ci    MessageHandler::Instance()->SendMessage(msg);
174722736c2fSopenharmony_ci}
174822736c2fSopenharmony_ci
174922736c2fSopenharmony_civoid InputMethodSystemAbility::StopImeInBackground()
175022736c2fSopenharmony_ci{
175122736c2fSopenharmony_ci    auto task = [this]() {
175222736c2fSopenharmony_ci        auto sessions = UserSessionManager::GetInstance().GetUserSessions();
175322736c2fSopenharmony_ci        for (const auto &tempSession : sessions) {
175422736c2fSopenharmony_ci            if (tempSession.first != userId_) {
175522736c2fSopenharmony_ci                tempSession.second->StopCurrentIme();
175622736c2fSopenharmony_ci            }
175722736c2fSopenharmony_ci        }
175822736c2fSopenharmony_ci    };
175922736c2fSopenharmony_ci    serviceHandler_->PostTask(task, "StopImeInBackground", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
176022736c2fSopenharmony_ci}
176122736c2fSopenharmony_ci
176222736c2fSopenharmony_ciint32_t InputMethodSystemAbility::GetUserId(int32_t uid)
176322736c2fSopenharmony_ci{
176422736c2fSopenharmony_ci    IMSA_HILOGD("uid:%{public}d", uid);
176522736c2fSopenharmony_ci    auto userId = OsAccountAdapter::GetOsAccountLocalIdFromUid(uid);
176622736c2fSopenharmony_ci    // 0 represents user 0 in the system
176722736c2fSopenharmony_ci    if (userId == 0) {
176822736c2fSopenharmony_ci        IMSA_HILOGI("user 0");
176922736c2fSopenharmony_ci        return userId_;
177022736c2fSopenharmony_ci    }
177122736c2fSopenharmony_ci    return userId;
177222736c2fSopenharmony_ci}
177322736c2fSopenharmony_ci
177422736c2fSopenharmony_ciint32_t InputMethodSystemAbility::GetCallingUserId()
177522736c2fSopenharmony_ci{
177622736c2fSopenharmony_ci    auto uid = IPCSkeleton::GetCallingUid();
177722736c2fSopenharmony_ci    return GetUserId(uid);
177822736c2fSopenharmony_ci}
177922736c2fSopenharmony_ci
178022736c2fSopenharmony_cibool InputMethodSystemAbility::IsCurrentIme(int32_t userId)
178122736c2fSopenharmony_ci{
178222736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
178322736c2fSopenharmony_ci    if (session == nullptr) {
178422736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
178522736c2fSopenharmony_ci        return false;
178622736c2fSopenharmony_ci    }
178722736c2fSopenharmony_ci    auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
178822736c2fSopenharmony_ci    if (bundleName.empty()) {
178922736c2fSopenharmony_ci        IMSA_HILOGW("user:%{public}d tokenId:%{public}d not find.", userId, IPCSkeleton::GetCallingTokenID());
179022736c2fSopenharmony_ci        bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
179122736c2fSopenharmony_ci    }
179222736c2fSopenharmony_ci    auto imeData = session->GetImeData(ImeType::IME);
179322736c2fSopenharmony_ci    return imeData != nullptr && bundleName == imeData->ime.first;
179422736c2fSopenharmony_ci}
179522736c2fSopenharmony_ci
179622736c2fSopenharmony_ciint32_t InputMethodSystemAbility::StartInputType(int32_t userId, InputType type)
179722736c2fSopenharmony_ci{
179822736c2fSopenharmony_ci    auto session = UserSessionManager::GetInstance().GetUserSession(userId);
179922736c2fSopenharmony_ci    if (session == nullptr) {
180022736c2fSopenharmony_ci        IMSA_HILOGE("%{public}d session is nullptr!", userId);
180122736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
180222736c2fSopenharmony_ci    }
180322736c2fSopenharmony_ci    ImeIdentification ime;
180422736c2fSopenharmony_ci    int32_t ret = InputTypeManager::GetInstance().GetImeByInputType(type, ime);
180522736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
180622736c2fSopenharmony_ci        IMSA_HILOGW("not find input type: %{public}d.", type);
180722736c2fSopenharmony_ci        // add for not adapter for SECURITY_INPUT
180822736c2fSopenharmony_ci        if (type == InputType::SECURITY_INPUT) {
180922736c2fSopenharmony_ci            return session->RestoreCurrentIme();
181022736c2fSopenharmony_ci        }
181122736c2fSopenharmony_ci        return ret;
181222736c2fSopenharmony_ci    }
181322736c2fSopenharmony_ci    SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName };
181422736c2fSopenharmony_ci    session->GetSwitchQueue().Push(switchInfo);
181522736c2fSopenharmony_ci    IMSA_HILOGI("start input type: %{public}d.", type);
181622736c2fSopenharmony_ci    return type == InputType::SECURITY_INPUT ? OnStartInputType(userId, switchInfo, false)
181722736c2fSopenharmony_ci                                             : OnStartInputType(userId, switchInfo, true);
181822736c2fSopenharmony_ci}
181922736c2fSopenharmony_ci
182022736c2fSopenharmony_civoid InputMethodSystemAbility::NeedHideWhenSwitchInputType(int32_t userId, bool &needHide)
182122736c2fSopenharmony_ci{
182222736c2fSopenharmony_ci    ImeIdentification ime;
182322736c2fSopenharmony_ci    InputTypeManager::GetInstance().GetImeByInputType(InputType::SECURITY_INPUT, ime);
182422736c2fSopenharmony_ci    auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
182522736c2fSopenharmony_ci    if (currentImeCfg == nullptr) {
182622736c2fSopenharmony_ci        IMSA_HILOGI("currentImeCfg is nullptr");
182722736c2fSopenharmony_ci        return;
182822736c2fSopenharmony_ci    }
182922736c2fSopenharmony_ci    needHide = currentImeCfg->bundleName == ime.bundleName;
183022736c2fSopenharmony_ci}
183122736c2fSopenharmony_ci} // namespace MiscServices
183222736c2fSopenharmony_ci} // namespace OHOS