/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SERVICES_INCLUDE_PERUSER_SESSION_H
#define SERVICES_INCLUDE_PERUSER_SESSION_H

#include <unordered_set>

#include "block_queue.h"
#include "client_group.h"
#include "event_status_manager.h"
#include "iinput_method_core.h"
#include "ime_connection.h"
#include "ime_enabled_info_manager.h"
#include "ime_state_manager.h"
#include "input_method_client_types.h"
#include "input_method_types.h"
#include "input_type_manager.h"
#include "inputmethod_message_handler.h"
#include "inputmethod_sysevent.h"
#include "want.h"
namespace OHOS {
namespace Rosen {
struct CallingWindowInfo;
}
}
namespace OHOS {
namespace MiscServices {
const std::string IME_MIRROR_NAME = "proxyIme_IME_MIRROR";
const std::string PROXY_IME_NAME = "proxyIme";
enum class ImeStartScene : uint32_t { MAKE_IMAGE, NORMAL_START };
enum class ImageFailedReason : uint32_t { FAILED_HAS_RUNNING_IME, FAILED_OTHERS, FAILED_NONE};
enum class ImeStatus : uint32_t { STARTING, READY, EXITING };
enum class ImeEvent : uint32_t {
    START_IME,
    START_IME_TIMEOUT,
    STOP_IME,
    SET_CORE_AND_AGENT,
};
enum LargeMemoryState : int32_t {
    LARGE_MEMORY_NEED = 2,
    LARGE_MEMORY_NOT_NEED = 3
};
enum class ImeAction : uint32_t {
    DO_NOTHING,
    HANDLE_STARTING_IME,
    FORCE_STOP_IME,
    STOP_READY_IME,
    START_AFTER_FORCE_STOP,
    DO_SET_CORE_AND_AGENT,
    DO_ACTION_IN_NULL_IME_DATA,
    DO_ACTION_IN_IME_EVENT_CONVERT_FAILED,
};
struct ImeData {
    static constexpr int64_t START_TIME_OUT = 18000;
    sptr<IInputMethodCore> core{ nullptr };
    sptr<IRemoteObject> agent{ nullptr };
    sptr<InputDeathRecipient> deathRecipient{ nullptr };
    pid_t pid{ ImfCommonConst::INVALID_PID };
    pid_t uid{ ImfCommonConst::INVALID_UID };
    ImeType type{ ImeType::IME };
    std::shared_ptr<ImeStateManager> imeStateManager;
    ImeStatus imeStatus{ ImeStatus::STARTING };
    std::pair<std::string, std::string> ime; // first: bundleName  second:extName
    int64_t startTime{ 0 };
    bool isStartedInScreenLocked = false;
    sptr<AAFwk::IAbilityConnection> connection{ nullptr };
    ImeData(sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, sptr<InputDeathRecipient> deathRecipient,
            pid_t imePid)
        : core(std::move(core)), agent(std::move(agent)), deathRecipient(std::move(deathRecipient)), pid(imePid)
    {
    }

    bool IsImeMirror() const
    {
        return type == ImeType::IME_MIRROR;
    }
    bool IsRealIme() const
    {
        return type == ImeType::IME;
    }
    ImeExtendInfo imeExtendInfo;
    bool isDisconnected = false;
};

enum class StartPreDefaultImeStatus : uint32_t { NO_NEED, HAS_STARTED, TO_START };
/**@class PerUserSession
 *
 * @brief The class provides session management in input method management service
 *
 * This class manages the sessions between input clients and input method engines for each unlocked user.
 */
class PerUserSession : public std::enable_shared_from_this<PerUserSession> {
public:
    PerUserSession(int32_t userId, const std::shared_ptr<AppExecFwk::EventHandler> &eventHandler);
    ~PerUserSession();

    int32_t OnPrepareInput(const InputClientInfo &clientInfo);
    int32_t OnStartInput(InputClientInfo &inputClientInfo, std::vector<sptr<IRemoteObject>> &agents,
        std::vector<BindImeInfo> &imeInfos);
    int32_t OnReleaseInput(const sptr<IInputClient> &client, uint32_t sessionId, int32_t clientSessionId);
    int32_t OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent);
    int32_t OnHideCurrentInput(uint64_t displayGroupId);
    int32_t OnHideCurrentInputInTargetDisplay(uint64_t displayId);
    int32_t OnShowCurrentInput(uint64_t displayGroupId);
    int32_t OnShowCurrentInputInTargetDisplay(uint64_t displayId);
    int32_t OnShowInput(sptr<IInputClient> client, int32_t requestKeyboardReason = 0);
    int32_t OnHideInput(sptr<IInputClient> client);
    int32_t OnRequestHideInput(uint64_t displayId, const std::string &callerBundleName);
    void OnSecurityChange(int32_t security);
    void OnHideSoftKeyBoardSelf();
    int32_t SwitchSubtype(const SubProperty &subProperty);
    int32_t SwitchSubtypeWithoutStartIme(const SubProperty &subProperty);
    void OnScbStarted(bool isScbReboot);
    void OnScbStopped();
    void OnFocused(uint64_t displayId, int32_t pid, int32_t uid);
    void OnUnfocused(uint64_t displayId, int32_t pid, int32_t uid);
    void OnScreenUnlock();
    void OnScreenLock();
    int32_t OnPackageUpdated(const std::string &bundleName);
    int64_t GetCurrentClientPid(uint64_t displayId);
    int64_t GetInactiveClientPid(uint64_t displayId);
    int32_t OnRegisterProxyIme(uint64_t displayId, const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent,
        int32_t pid, int32_t uid);
    int32_t OnBindImeMirror(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent);
    int32_t OnUnbindImeMirror();
    int32_t UpdateLargeMemorySceneState(const int32_t memoryState);
    int32_t OnUnregisterProxyIme(uint64_t displayId, int32_t pid, UnRegisteredType type);
    int32_t InitConnect(pid_t pid);

    int32_t StartCurrentIme(bool isStopCurrentIme = false, StartReason startReason = StartReason::DEFAULT_START);
    int32_t StartIme(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme = false);
    int32_t StopCurrentIme();
    bool RestartIme();
    void AddRestartIme();

    bool IsEnable(const std::shared_ptr<ImeData> &data, uint64_t displayId);
    bool IsBoundToClient(uint64_t displayId);
    bool IsCurrentImeByPid(int32_t pid);
    int32_t RestoreCurrentImeSubType();
    int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown);
    int32_t IsPanelShown(uint64_t displayId, const PanelInfo &panelInfo, bool &isShown);
    int32_t OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent);
    int32_t RemoveAllCurrentClient();
    std::shared_ptr<ImeData> GetReadyImeDataToBind(uint64_t displayId);
    std::shared_ptr<ImeData> GetRealImeData(bool isReady = false);
    BlockQueue<SwitchInfo>& GetSwitchQueue();
    bool IsWmsReady();
    bool CheckPwdInputPatternConv(InputClientInfo &clientInfo, uint64_t displayId);
    int32_t StartUserSpecifiedIme();
    int32_t SetInputType(std::shared_ptr<InputClientInfo> clientInfo);
    std::shared_ptr<ImeNativeCfg> GetImeNativeCfg(int32_t userId, const std::string &bundleName,
        const std::string &subName);
    int32_t OnSetCallingWindow(const FocusedInfo &focusedInfo, sptr<IInputClient> client, uint32_t windowId);
    bool IsKeyboardCallingProcess(int32_t pid, uint32_t windowId);
    int32_t GetInputStartInfo(InputStartInfo &inputStartInfo);
    bool IsSaReady(int32_t saId);
    void TryUnloadSystemAbility();
    void OnWindowDisplayIdChanged(int32_t windowId, uint64_t displayId);
    bool SpecialScenarioCheck();
    int32_t SpecialSendPrivateData(const std::unordered_map<std::string, PrivateDataValue> &privateCommand);
    int32_t SendVoicePrivateCommand(const bool isPersistence);
    bool IsNumkeyAutoInputApp(const std::string &bundleName);
    bool IsPreconfiguredDefaultImeSpecified(const InputClientInfo &inputClientInfo);
    bool IsImeSwitchForbidden();
    std::pair<int32_t, StartPreDefaultImeStatus> StartPreconfiguredDefaultIme(
        const ImeExtendInfo &imeExtendInfo = {}, bool isStopCurrentIme = false);
    void NotifyOnInputStopFinished();
    void IncreaseAttachCount();
    void DecreaseAttachCount();
    uint32_t GetAttachCount();
    void IncreaseScbStartCount();
    int32_t TryStartIme();
    int32_t TryDisconnectIme();
    bool IsDeviceLockAndScreenLocked();
    std::pair<std::shared_ptr<ClientGroup>, std::shared_ptr<InputClientInfo>> GetClientBySelfPid(pid_t clientPid);
    std::pair<std::shared_ptr<ClientGroup>, std::shared_ptr<InputClientInfo>> GetClientBySelfPidOrHostPid(
        pid_t clientPid);
    void OnSysImeImageCreated();
    int32_t OnMakeSysImeImage();
    bool IsImeInUse();
    int32_t GetSoftKeyboardInfo(BoundImeInfo &imeInfo);
    int32_t NotifyImeChangedToClients();
    int32_t GetCursorInfo(CursorInfoInner &cursorInfo, const pid_t clientPid);
    void OnImeDisconnect(sptr<ImeConnection> connection);
    void SetAttachFailedByUnavailableImeFlag(bool flag);
private:
    struct ResetManager {
        uint32_t num{ 0 };
        time_t last{};
    };
    enum TimeLimitType : uint32_t {
        IME_LIMIT,
        PROXY_IME_LIMIT,
    };
    using CoreMethod = std::function<int32_t(const sptr<IInputMethodCore> &)>;

    int32_t userId_; // the id of the user to whom the object is linking
#ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
    static const int MAX_IME_START_TIME = 2000;
#else
    static const int MAX_IME_START_TIME = 1500;
#endif
    static const int MAX_NOTIFY_TIME = 10; //10ms
    std::mutex resetLock;
    std::map<TimeLimitType, ResetManager> managers_;
    using IpcExec = std::function<int32_t()>;

    PerUserSession(const PerUserSession &);
    PerUserSession &operator=(const PerUserSession &);
    PerUserSession(const PerUserSession &&);
    PerUserSession &operator=(const PerUserSession &&);

    static constexpr int32_t MAX_WAIT_TIME = 5000;
    BlockQueue<SwitchInfo> switchQueue_{ MAX_WAIT_TIME };

    void OnClientDied(sptr<IInputClient> remote);
    void OnImeDied(const sptr<IInputMethodCore> &remote, ImeType type, pid_t pid);
    int AddClientInfo(sptr<IRemoteObject> inputClient, const InputClientInfo &clientInfo);
    int32_t RemoveClient(const sptr<IInputClient> &client, const std::shared_ptr<ClientGroup> &clientGroup,
        const DetachOptions &options);
    void DeactivateClient(const sptr<IInputClient> &client, const std::shared_ptr<ClientGroup> &clientGroup);
    std::shared_ptr<InputClientInfo> GetCurrentClientInfo(uint64_t displayId = DEFAULT_DISPLAY_ID);
    std::shared_ptr<ClientGroup> GetClientGroup(uint64_t displayId);
    std::shared_ptr<ClientGroup> GetClientGroup(sptr<IRemoteObject> client);
    std::shared_ptr<ClientGroup> GetClientGroupByGroupId(uint64_t displayGroupId);
    int32_t InitRealImeData(sptr<AAFwk::IAbilityConnection> &connection, bool &isFirstStart,
        const std::pair<std::string, std::string> &ime, const std::shared_ptr<ImeNativeCfg> &imeNativeCfg = nullptr);
    std::shared_ptr<ImeData> UpdateRealImeData(sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid,
        pid_t uid);
    std::shared_ptr<ImeData> GetRealImeData(pid_t pid);
    void RemoveRealImeData();
    void RemoveRealImeData(pid_t pid);
    std::shared_ptr<ImeData> AddProxyImeData(
        uint64_t displayId, sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid, pid_t uid);
    void AddProxyImeData(uint64_t displayId,
        std::vector<std::shared_ptr<ImeData>> &imeDataList, const std::shared_ptr<ImeData> &imeData);
    int32_t RemoveProxyImeData(uint64_t displayId, pid_t pid);
    void RemoveProxyImeData(pid_t pid);
    std::shared_ptr<ImeData> GetProxyImeData(pid_t pid);
    std::shared_ptr<ImeData> AddMirrorImeData(
        const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent, pid_t pid, pid_t uid);
    std::shared_ptr<ImeData> GetMirrorImeData();
    std::shared_ptr<ImeData> GetMirrorImeData(pid_t pid);
    void RemoveMirrorImeData(pid_t pid);
    void RemoveImeData(pid_t pid);
    std::shared_ptr<ImeData> GetImeData(pid_t pid, ImeType type);
    std::shared_ptr<ImeData> GetImeData(const std::shared_ptr<BindImeData> &bindImeData);
    int32_t FillImeData(sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid, ImeType type,
        std::shared_ptr<ImeData> &imeData, pid_t uid);
    int32_t BindClientWithIme(const std::shared_ptr<InputClientInfo> &clientInfo,
        const std::shared_ptr<ImeData> &imeData, bool isBindFromClient = false);
    void UnBindClientWithIme(const std::shared_ptr<InputClientInfo> &currentClientInfo, const DetachOptions &options);
    void StopClientInput(const std::shared_ptr<InputClientInfo> &clientInfo, DetachOptions options = {});
    void StopImeInput(const std::shared_ptr<ImeData> &imeData, const std::shared_ptr<InputClientInfo> &clientInfo,
        uint32_t sessionId, int32_t clientSessionId = -1);

    int32_t HideKeyboard(const sptr<IInputClient> &currentClient, const std::shared_ptr<ClientGroup> &clientGroup);
    int32_t ShowKeyboard(const sptr<IInputClient> &currentClient, const std::shared_ptr<ClientGroup> &clientGroup,
        int32_t requestKeyboardReason = 0);
    bool RequestHideRealIme(uint64_t displayGroupId);
    bool RequestHideProxyIme(uint64_t displayId);
    int32_t UpdateClientAfterRequestHide(uint64_t displayGroupId, const std::string &callerBundleName);

    int32_t InitInputControlChannel();
    void StartImeInImeDied();
    void StartImeIfInstalled(StartReason startReason = StartReason::DEFAULT_START);
    void ReplaceCurrentClient(const sptr<IInputClient> &client, const std::shared_ptr<ClientGroup> &clientGroup);
    bool IsSameClient(sptr<IInputClient> source, sptr<IInputClient> dest);
    int32_t RequestIme(const std::shared_ptr<ImeData> &data, RequestType type, const IpcExec &exec);
    int32_t RequestAllIme(
        const std::shared_ptr<ImeData> &data, RequestType reqType, const CoreMethod &method, uint64_t groupId);
    std::vector<std::shared_ptr<ImeData>> GetAllReadyImeData(const std::shared_ptr<ImeData> &imeData, uint64_t groupId);

    bool WaitForCurrentImeStop();
    void NotifyImeStopFinished();
    bool CanStartIme();
    int32_t ChangeToDefaultImeIfNeed(
        const std::shared_ptr<ImeNativeCfg> &ime, std::shared_ptr<ImeNativeCfg> &imeToStart);
    AAFwk::Want GetWant(const std::shared_ptr<ImeNativeCfg> &ime);
    int32_t StartCurrentIme(const std::shared_ptr<ImeNativeCfg> &ime);
    int32_t StartNewIme(const std::shared_ptr<ImeNativeCfg> &ime);
    int32_t StartInputService(const std::shared_ptr<ImeNativeCfg> &ime, bool skipWaitAfterTimeout = true);
    int32_t ForceStopCurrentIme(bool isNeedWait = true);
    int32_t StopReadyCurrentIme();
    int32_t HandleFirstStart(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme);
    int32_t HandleStartImeTimeout(const std::shared_ptr<ImeNativeCfg> &ime);
    bool GetInputTypeToStart(std::shared_ptr<ImeNativeCfg> &imeToStart);
    void HandleBindImeChanged(InputClientInfo &newClientInfo, const std::shared_ptr<ImeData> &newImeData,
        const std::shared_ptr<ClientGroup> &clientGroup);
    int32_t NotifyCallingDisplayChanged(
        uint64_t editorDisplayId, uint64_t keyboardDisplayId, const std::shared_ptr<ImeData> &imeData);
    int32_t NotifyCallingWindowIdChanged(
        uint32_t rawEditorWindowId, const FocusedInfo &focusedInfo, const std::shared_ptr<ImeData> &imeData);
    int32_t SendPrivateData(const std::unordered_map<std::string, PrivateDataValue> &privateCommand);
    void ClearRequestKeyboardReason(std::shared_ptr<InputClientInfo> &clientInfo);
    std::pair<std::string, std::string> GetImeUsedBeforeScreenLocked();
    void SetImeUsedBeforeScreenLocked(const std::pair<std::string, std::string> &ime);
    std::shared_ptr<ImeNativeCfg> GetRealCurrentIme(bool needMinGuarantee);
    int32_t NotifySubTypeChangedToIme(const std::string &bundleName, const std::string &subName);
    bool CompareExchange(const int32_t value);
    bool IsLargeMemoryStateNeed();
    bool IsAttachFinished();
    uint32_t GetScbStartCount();
    void ResetRestartTasks();
    int32_t SendAllReadyImeToClient(
        std::shared_ptr<ImeData> data, const std::shared_ptr<InputClientInfo> &clientInfo);
    int32_t IsRequestOverLimit(TimeLimitType timeLimit, int32_t resetTimeOut, uint32_t restartNum);
    int32_t PrepareImeInfos(const std::shared_ptr<ImeData> &imeData, std::vector<sptr<IRemoteObject>> &agents,
        std::vector<BindImeInfo> &imeInfos, uint64_t groupId);
    int32_t PostCurrentImeInfoReportHook(const std::string &bundleName);
    std::shared_ptr<ImeData> GetProxyImeData(uint64_t displayId);
    std::pair<std::shared_ptr<ClientGroup>, std::shared_ptr<InputClientInfo>> GetCurrentClientBoundRealIme();
    std::pair<std::shared_ptr<ClientGroup>, std::shared_ptr<InputClientInfo>> GetClientBoundImeByImePid(
        pid_t bindImePid);
    std::pair<std::shared_ptr<ClientGroup>, std::shared_ptr<InputClientInfo>> GetClientBoundImeByWindowId(
        uint32_t windowId);
    std::pair<std::shared_ptr<ClientGroup>, std::shared_ptr<InputClientInfo>> GetClientBoundRealIme();
    bool IsSameIme(const std::shared_ptr<BindImeData> &oldIme, const std::shared_ptr<ImeData> &newIme);
    bool IsShowSameRealImeInMainDisplayInMultiGroup(
        InputClientInfo &newClientInfo, const std::shared_ptr<InputClientInfo> &oldClientInfo);
    bool IsSameImeType(const std::shared_ptr<BindImeData> &oldIme, const std::shared_ptr<ImeData> &newIme);
    bool IsSameClientGroup(uint64_t oldGroupId, uint64_t newGroupId);
    void HandleSameClientInMultiGroup(const InputClientInfo &newClientInfo);
    void HandleRealImeInMultiGroup(const InputClientInfo &newClientInfo, const std::shared_ptr<ImeData> &newImeData);
    void HandleSameImeInMultiGroup(const InputClientInfo &newClientInfo, const std::shared_ptr<ImeData> &newImeData);
    void HandleInMultiGroup(const InputClientInfo &newClientInfo, const std::shared_ptr<ClientGroup> &oldClientGroup,
        const std::shared_ptr<InputClientInfo> &oldClientInfo, bool needStopIme = false);
    void HandleWindowIdChanged(
        const FocusedInfo &focusedInfo, const std::shared_ptr<InputClientInfo> &clientInfo, uint32_t windowId);
    void RemoveDeathRecipient(const sptr<InputDeathRecipient> &deathRecipient, const sptr<IRemoteObject> &object);
    bool IsDefaultGroup(uint64_t clientGroupId);
    bool NeedHideRealIme(uint64_t clientGroupId);
    std::pair<bool, ImageFailedReason> NeedMakeImage(const std::string &bundleName, const std::string &extName);
    std::pair<bool, ImageFailedReason> MakeImage(const std::string &bundleName, const std::string &extName);
    int32_t StartImeInSysImageChanged();
    bool NeedStartIme(ImeStartScene scene);
    void StartImageTimeoutTask();
    void StopImageTimeoutTask();
    int32_t HandleSysImeInDied(ImeType type, bool disconnectedByRss);
    void UpdateRealImeDataOnDisconnect(sptr<ImeConnection> connection);
    bool IsImeDisconnected(pid_t pid);
    bool WaitImeExtExit(ImeType type, pid_t pid);
    std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler();
    void RemoveAllTask();
    struct TaskNames {
        std::string imageTimeout;
        std::string imeInfoReportHook;
        std::string restartIme;
        std::vector<std::string> GetAllTaskNames() const
        {
            return { imageTimeout, imeInfoReportHook, restartIme };
        }
        static TaskNames MakeTaskNames(int32_t userId)
        {
            auto make = [userId](const char *name) { return std::string(name) + "_" + std::to_string(userId); };
            return {
                .imageTimeout = make("imf_imageTimeoutTask"),
                .imeInfoReportHook = make("imf_executeCurrentImeInfoReportHook"),
                .restartIme = make("imf_restartCurrentIme"),
            };
        }
    };
    void NotifyInputStop(uint64_t displayId, InputStopScene scene, bool isRealIme);
    std::mutex imeStartLock_;

    BlockData<bool> isImeStarted_{ MAX_IME_START_TIME, false };
    std::mutex focusedClientLock_;

    std::atomic<bool> isSwitching_ = false;
    std::mutex imeStopMutex_;
    std::condition_variable imeStopCv_;

    std::mutex restartMutex_;
    int32_t restartTasks_ = 0;
    std::shared_ptr<AppExecFwk::EventHandler> eventHandler_{ nullptr };
    const TaskNames taskNames_;
    ImeAction GetImeAction(ImeEvent action);
    static inline const std::map<std::pair<ImeStatus, ImeEvent>, std::pair<ImeStatus, ImeAction>> imeEventConverter_ = {
        { { ImeStatus::READY, ImeEvent::START_IME }, { ImeStatus::READY, ImeAction::DO_NOTHING } },
        { { ImeStatus::STARTING, ImeEvent::START_IME }, { ImeStatus::STARTING, ImeAction::HANDLE_STARTING_IME } },
        { { ImeStatus::EXITING, ImeEvent::START_IME }, { ImeStatus::EXITING, ImeAction::START_AFTER_FORCE_STOP } },
        { { ImeStatus::READY, ImeEvent::START_IME_TIMEOUT }, { ImeStatus::READY, ImeAction::DO_NOTHING } },
        { { ImeStatus::STARTING, ImeEvent::START_IME_TIMEOUT },
            { ImeStatus::EXITING, ImeAction::START_AFTER_FORCE_STOP } },
        { { ImeStatus::EXITING, ImeEvent::START_IME_TIMEOUT },
            { ImeStatus::EXITING, ImeAction::START_AFTER_FORCE_STOP } },
        { { ImeStatus::READY, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::STOP_READY_IME } },
        { { ImeStatus::STARTING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::FORCE_STOP_IME } },
        { { ImeStatus::EXITING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::FORCE_STOP_IME } },
        { { ImeStatus::READY, ImeEvent::SET_CORE_AND_AGENT }, { ImeStatus::READY, ImeAction::DO_NOTHING } },
        { { ImeStatus::STARTING, ImeEvent::SET_CORE_AND_AGENT },
            { ImeStatus::READY, ImeAction::DO_SET_CORE_AND_AGENT } },
        { { ImeStatus::EXITING, ImeEvent::SET_CORE_AND_AGENT }, { ImeStatus::EXITING, ImeAction::DO_NOTHING } }
    };
    std::string runningIme_;
    std::mutex imeUsedLock_;
    std::pair<std::string, std::string> imeUsedBeforeScreenLocked_;
    std::mutex largeMemoryStateMutex_{};
    int32_t largeMemoryState_ = LargeMemoryState::LARGE_MEMORY_NOT_NEED;
    std::mutex clientGroupLock_{};
    std::unordered_map<uint64_t, std::shared_ptr<ClientGroup>> clientGroupMap_;
    std::mutex isNotifyFinishedLock_{};
    BlockData<bool> isNotifyFinished_{ MAX_NOTIFY_TIME, false };
    std::mutex attachCountMtx_{};
    uint32_t attachingCount_ { 0 };
    std::mutex scbStartCountMtx_{};
    uint32_t scbStartCount_ { 0 };
    std::atomic<bool> isBlockStartedByLowMem_ = false;
    bool isFirstPreemption_ = false;
    std::mutex proxyImeDataLock_;
    std::map<uint64_t, std::vector<std::shared_ptr<ImeData>>> proxyImeData_;
    std::mutex mirrorImeDataLock_;
    std::shared_ptr<ImeData> mirrorImeData_;
    std::mutex realImeDataLock_;
    std::shared_ptr<ImeData> realImeData_{ nullptr };
    std::atomic<bool> firstStartNeedRetry_ { true };

    std::mutex imageTimeoutTaskLock_;
    std::atomic<bool> disconnectedByRss_{ false };
    std::atomic<bool> attachFailedByUnavailableIme_{ false };
};
} // namespace MiscServices
} // namespace OHOS
#endif // SERVICES_INCLUDE_PERUSER_SESSION_H