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