/* * 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 #include #include #include #include #include #include "block_data.h" #include "block_queue.h" #include "enable_ime_data_parser.h" #include "event_handler.h" #include "event_status_manager.h" #include "freeze_manager.h" #include "global.h" #include "i_input_client.h" #include "i_input_control_channel.h" #include "i_system_cmd_channel.h" #include "i_input_data_channel.h" #include "i_input_method_agent.h" #include "i_input_method_core.h" #include "ime_cfg_manager.h" #include "input_attribute.h" #include "input_client_info.h" #include "input_death_recipient.h" #include "input_method_info.h" #include "input_method_property.h" #include "input_type_manager.h" #include "input_window_info.h" #include "inputmethod_sysevent.h" #include "iremote_object.h" #include "message.h" #include "message_handler.h" #include "panel_info.h" #include "input_method_types.h" #include "want.h" namespace OHOS { namespace MiscServices { 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 class ImeAction : uint32_t { DO_NOTHING, HANDLE_STARTING_IME, STOP_EXITING_IME, STOP_READY_IME, STOP_STARTING_IME, 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 = 8000; sptr core{ nullptr }; sptr agent{ nullptr }; sptr deathRecipient{ nullptr }; pid_t pid; std::shared_ptr freezeMgr; ImeStatus imeStatus{ ImeStatus::STARTING }; std::pair ime; // first: bundleName second:extName int64_t startTime{ 0 }; ImeData(sptr core, sptr agent, sptr deathRecipient, pid_t imePid) : core(std::move(core)), agent(std::move(agent)), deathRecipient(std::move(deathRecipient)), pid(imePid), freezeMgr(std::make_shared(imePid)) { } }; /**@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: explicit PerUserSession(int userId); PerUserSession(int32_t userId, const std::shared_ptr &eventHandler); ~PerUserSession(); int32_t OnPrepareInput(const InputClientInfo &clientInfo); int32_t OnStartInput(const InputClientInfo &inputClientInfo, sptr &agent); int32_t OnReleaseInput(const sptr &client); int32_t OnSetCoreAndAgent(const sptr &core, const sptr &agent); int32_t OnHideCurrentInput(); int32_t OnShowCurrentInput(); int32_t OnShowInput(sptr client); int32_t OnHideInput(sptr client); int32_t OnRequestShowInput(); int32_t OnRequestHideInput(); void OnSecurityChange(int32_t security); void OnHideSoftKeyBoardSelf(); void NotifyImeChangeToClients(const Property &property, const SubProperty &subProperty); int32_t SwitchSubtype(const SubProperty &subProperty); int32_t SwitchSubtypeWithoutStartIme(const SubProperty &subProperty); void OnFocused(int32_t pid, int32_t uid); void OnUnfocused(int32_t pid, int32_t uid); void OnUserUnlocked(); int64_t GetCurrentClientPid(); int64_t GetInactiveClientPid(); int32_t OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info); int32_t OnUpdateListenEventFlag(const InputClientInfo &clientInfo); int32_t OnRegisterProxyIme(const sptr &core, const sptr &agent); int32_t OnUnRegisteredProxyIme(UnRegisteredType type, const sptr &core); int32_t InitConnect(pid_t pid); bool StartCurrentIme(bool isStopCurrentIme = false); bool StartIme(const std::shared_ptr &ime, bool isStopCurrentIme = false); bool StopCurrentIme(); bool RestartIme(); void AddRestartIme(); bool IsProxyImeEnable(); bool IsBoundToClient(); bool IsCurrentImeByPid(int32_t pid); int32_t RestoreCurrentImeSubType(); int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown); bool CheckSecurityMode(); int32_t OnConnectSystemCmd(const sptr &channel, sptr &agent); int32_t RemoveCurrentClient(); std::shared_ptr GetReadyImeData(ImeType type); std::shared_ptr GetImeData(ImeType type); BlockQueue& GetSwitchQueue(); bool IsWmsReady(); bool CheckPwdInputPatternConv(InputClientInfo &clientInfo); int32_t RestoreCurrentIme(); std::shared_ptr GetImeNativeCfg(int32_t userId, const std::string &bundleName, const std::string &subName); void UpdateUserLockState(); private: struct ResetManager { uint32_t num{ 0 }; time_t last{}; }; enum ClientAddEvent : int32_t { PREPARE_INPUT = 0, START_LISTENING, }; int32_t userId_; // the id of the user to whom the object is linking std::recursive_mutex mtx; std::map, std::shared_ptr> mapClients_; static const int MAX_RESTART_NUM = 3; static const int IME_RESET_TIME_OUT = 3; static const int MAX_IME_START_TIME = 1000; static constexpr int32_t MAX_RESTART_TASKS = 2; std::mutex clientLock_; sptr currentClient_; // the current input client std::mutex resetLock; ResetManager manager; using IpcExec = std::function; PerUserSession(const PerUserSession &); PerUserSession &operator=(const PerUserSession &); PerUserSession(const PerUserSession &&); PerUserSession &operator=(const PerUserSession &&); static constexpr int32_t MAX_WAIT_TIME = 5000; BlockQueue switchQueue_{ MAX_WAIT_TIME }; void OnClientDied(sptr remote); void OnImeDied(const sptr &remote, ImeType type); int AddClientInfo(sptr inputClient, const InputClientInfo &clientInfo, ClientAddEvent event); void RemoveClientInfo(const sptr &client, bool isClientDied = false); int32_t RemoveClient( const sptr &client, bool isUnbindFromClient = false, bool isInactiveClient = false); void DeactivateClient(const sptr &client); std::shared_ptr GetClientInfo(sptr inputClient); std::shared_ptr GetClientInfo(pid_t pid); std::shared_ptr GetCurClientInfo(); void UpdateClientInfo(const sptr &client, const std::unordered_map> &updateInfos); int32_t InitImeData(const std::pair &ime); int32_t UpdateImeData(sptr core, sptr agent, pid_t pid); int32_t AddImeData(ImeType type, sptr core, sptr agent, pid_t pid); void RemoveImeData(ImeType type, bool isImeDied); int32_t RemoveIme(const sptr &core, ImeType type); std::shared_ptr GetValidIme(ImeType type); int32_t BindClientWithIme( const std::shared_ptr &clientInfo, ImeType type, bool isBindFromClient = false); void UnBindClientWithIme( const std::shared_ptr ¤tClientInfo, bool isUnbindFromClient = false); void StopClientInput(const std::shared_ptr &clientInfo, bool isStopInactiveClient = false); void StopImeInput(ImeType currentType, const sptr ¤tChannel); int32_t HideKeyboard(const sptr ¤tClient); int32_t ShowKeyboard(const sptr ¤tClient); int32_t InitInputControlChannel(); void StartImeInImeDied(); void SetCurrentClient(sptr client); sptr GetCurrentClient(); void ReplaceCurrentClient(const sptr &client); void SetInactiveClient(sptr client); sptr GetInactiveClient(); bool IsCurClientFocused(int32_t pid, int32_t uid); bool IsCurClientUnFocused(int32_t pid, int32_t uid); bool IsSameClient(sptr source, sptr dest); bool IsImeStartInBind(ImeType bindImeType, ImeType startImeType); bool IsProxyImeStartInBind(ImeType bindImeType, ImeType startImeType); bool IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType); bool IsImeBindChanged(ImeType bindImeType); std::map, std::shared_ptr> GetClientMap(); int32_t RequestIme(const std::shared_ptr &data, RequestType type, const IpcExec &exec); bool WaitForCurrentImeStop(); void NotifyImeStopFinished(); bool GetCurrentUsingImeId(ImeIdentification &imeId); bool CanStartIme(); int32_t ChangeToDefaultImeIfNeed( const std::shared_ptr &ime, std::shared_ptr &imeToStart); bool IsReady(int32_t saId); AAFwk::Want GetWant(const std::shared_ptr &ime); bool StartCurrentIme(const std::shared_ptr &ime); bool StartNewIme(const std::shared_ptr &ime); bool StartInputService(const std::shared_ptr &ime); bool ForceStopCurrentIme(bool isNeedWait = true); bool StopReadyCurrentIme(); bool StopExitingCurrentIme(); bool HandleFirstStart(const std::shared_ptr &ime, bool isStopCurrentIme); bool HandleStartImeTimeout(const std::shared_ptr &ime); bool GetInputTypeToStart(std::shared_ptr &imeToStart); std::mutex imeStartLock_; BlockData isImeStarted_{ MAX_IME_START_TIME, false }; std::mutex imeDataLock_; std::unordered_map> imeData_; std::mutex inactiveClientLock_; sptr inactiveClient_; // the inactive input client std::mutex focusedClientLock_; std::atomic isSwitching_ = false; std::mutex imeStopMutex_; std::condition_variable imeStopCv_; std::mutex restartMutex_; int32_t restartTasks_ = 0; std::shared_ptr eventHandler_{ nullptr }; ImeAction GetImeAction(ImeEvent action); static inline const std::map, std::pair> 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::STOP_EXITING_IME } }, { { ImeStatus::READY, ImeEvent::START_IME_TIMEOUT }, { ImeStatus::READY, ImeAction::DO_NOTHING } }, { { ImeStatus::STARTING, ImeEvent::START_IME_TIMEOUT }, { ImeStatus::EXITING, ImeAction::STOP_EXITING_IME } }, { { ImeStatus::EXITING, ImeEvent::START_IME_TIMEOUT }, { ImeStatus::EXITING, ImeAction::STOP_EXITING_IME } }, { { ImeStatus::READY, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::STOP_READY_IME } }, { { ImeStatus::STARTING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::STOP_STARTING_IME } }, { { ImeStatus::EXITING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::STOP_EXITING_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::atomic isUserUnlocked_{ false }; }; } // namespace MiscServices } // namespace OHOS #endif // SERVICES_INCLUDE_PERUSER_SESSION_H