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