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