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