• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "peruser_session.h"
17 
18 #include <vector>
19 
20 #include "ability_manager_client.h"
21 #include "element_name.h"
22 #include "ime_aging_manager.h"
23 #include "ime_cfg_manager.h"
24 #include "ime_info_inquirer.h"
25 #include "input_client_proxy.h"
26 #include "input_control_channel_proxy.h"
27 #include "input_data_channel_proxy.h"
28 #include "input_method_agent_proxy.h"
29 #include "input_method_core_proxy.h"
30 #include "input_type_manager.h"
31 #include "ipc_skeleton.h"
32 #include "iservice_registry.h"
33 #include "message_parcel.h"
34 #include "parcel.h"
35 #include "scene_board_judgement.h"
36 #include "sys/prctl.h"
37 #include "system_ability_definition.h"
38 #include "unistd.h"
39 #include "want.h"
40 #include "wms_connection_observer.h"
41 
42 namespace OHOS {
43 namespace MiscServices {
44 using namespace MessageID;
45 constexpr uint32_t IME_RESTART_TIMES = 5;
46 constexpr uint32_t IME_RESTART_INTERVAL = 300;
47 constexpr int64_t INVALID_PID = -1;
PerUserSession(int32_t userId)48 PerUserSession::PerUserSession(int32_t userId) : userId_(userId)
49 {
50 }
51 
~PerUserSession()52 PerUserSession::~PerUserSession()
53 {
54 }
55 
AddClientInfo(sptr<IRemoteObject> inputClient,const InputClientInfo & clientInfo,ClientAddEvent event)56 int PerUserSession::AddClientInfo(
57     sptr<IRemoteObject> inputClient, const InputClientInfo &clientInfo, ClientAddEvent event)
58 {
59     IMSA_HILOGD("PerUserSession, run in");
60     auto cacheInfo = GetClientInfo(inputClient);
61     if (cacheInfo != nullptr) {
62         IMSA_HILOGD("info is existed");
63         UpdateClientInfo(inputClient, { { UpdateFlag::TEXT_CONFIG, clientInfo.config } });
64         if (event == START_LISTENING) {
65             UpdateClientInfo(inputClient, { { UpdateFlag::EVENTFLAG, clientInfo.eventFlag } });
66         }
67         return ErrorCode::NO_ERROR;
68     }
69     auto info = std::make_shared<InputClientInfo>(clientInfo);
70     info->deathRecipient->SetDeathRecipient(
71         [this, info](const wptr<IRemoteObject> &) { this->OnClientDied(info->client); });
72     auto obj = info->client->AsObject();
73     if (obj == nullptr) {
74         IMSA_HILOGE("client obj is nullptr");
75         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
76     }
77     if (!obj->AddDeathRecipient(info->deathRecipient)) {
78         IMSA_HILOGE("failed to add client death recipient");
79         return ErrorCode::ERROR_CLIENT_ADD_FAILED;
80     }
81     std::lock_guard<std::recursive_mutex> lock(mtx);
82     mapClients_.insert({ inputClient, info });
83     IMSA_HILOGI("add client end");
84     return ErrorCode::NO_ERROR;
85 }
86 
RemoveClientInfo(const sptr<IRemoteObject> & client,bool isClientDied)87 void PerUserSession::RemoveClientInfo(const sptr<IRemoteObject> &client, bool isClientDied)
88 {
89     std::lock_guard<std::recursive_mutex> lock(mtx);
90     auto clientInfo = GetClientInfo(client);
91     if (clientInfo == nullptr) {
92         IMSA_HILOGD("client already removed");
93         return;
94     }
95     // if client is subscriber and the release is not because of the client died, do not remove
96     if (clientInfo->eventFlag != EventStatusManager::NO_EVENT_ON && !isClientDied) {
97         IMSA_HILOGD("is subscriber, do not remove");
98         auto isShowKeyboard = false;
99         auto bindImeType = ImeType::NONE;
100         UpdateClientInfo(
101             client, { { UpdateFlag::BINDIMETYPE, bindImeType }, { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
102         return;
103     }
104     if (clientInfo->deathRecipient != nullptr) {
105         IMSA_HILOGD("deathRecipient remove");
106         client->RemoveDeathRecipient(clientInfo->deathRecipient);
107         clientInfo->deathRecipient = nullptr;
108     }
109     mapClients_.erase(client);
110     IMSA_HILOGI("client[%{public}d] is removed", clientInfo->pid);
111 }
112 
UpdateClientInfo(const sptr<IRemoteObject> & client,const std::unordered_map<UpdateFlag,std::variant<bool,uint32_t,ImeType,ClientState,TextTotalConfig>> & updateInfos)113 void PerUserSession::UpdateClientInfo(const sptr<IRemoteObject> &client,
114     const std::unordered_map<UpdateFlag, std::variant<bool, uint32_t, ImeType, ClientState, TextTotalConfig>>
115         &updateInfos)
116 {
117     if (client == nullptr) {
118         IMSA_HILOGE("client is nullptr.");
119         return;
120     }
121     auto info = GetClientInfo(client);
122     if (info == nullptr) {
123         IMSA_HILOGE("client info is not exist.");
124         return;
125     }
126     for (const auto &updateInfo : updateInfos) {
127         switch (updateInfo.first) {
128             case UpdateFlag::EVENTFLAG: {
129                 info->eventFlag = std::get<uint32_t>(updateInfo.second);
130                 break;
131             }
132             case UpdateFlag::ISSHOWKEYBOARD: {
133                 info->isShowKeyboard = std::get<bool>(updateInfo.second);
134                 break;
135             }
136             case UpdateFlag::BINDIMETYPE: {
137                 info->bindImeType = std::get<ImeType>(updateInfo.second);
138                 break;
139             }
140             case UpdateFlag::STATE: {
141                 info->state = std::get<ClientState>(updateInfo.second);
142                 break;
143             }
144             case UpdateFlag::TEXT_CONFIG: {
145                 info->config = std::get<TextTotalConfig>(updateInfo.second);
146                 break;
147             }
148             default:
149                 break;
150         }
151     }
152 }
153 
HideKeyboard(const sptr<IInputClient> & currentClient)154 int32_t PerUserSession::HideKeyboard(const sptr<IInputClient> &currentClient)
155 {
156     IMSA_HILOGD("PerUserSession::HideKeyboard");
157     auto clientInfo = GetClientInfo(currentClient->AsObject());
158     if (clientInfo == nullptr) {
159         IMSA_HILOGE("client info is nullptr");
160         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
161     }
162     auto data = GetImeData(clientInfo->bindImeType);
163     if (data == nullptr) {
164         IMSA_HILOGE("ime: %{public}d is not exist", clientInfo->bindImeType);
165         return ErrorCode::ERROR_IME_NOT_STARTED;
166     }
167     auto ret = data->core->HideKeyboard();
168     if (ret != ErrorCode::NO_ERROR) {
169         IMSA_HILOGE("failed to hide keyboard, ret: %{public}d", ret);
170         return ErrorCode::ERROR_KBD_HIDE_FAILED;
171     }
172     bool isShowKeyboard = false;
173     UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
174     ExitCurrentInputType();
175     return ErrorCode::NO_ERROR;
176 }
177 
ShowKeyboard(const sptr<IInputClient> & currentClient)178 int32_t PerUserSession::ShowKeyboard(const sptr<IInputClient> &currentClient)
179 {
180     IMSA_HILOGD("PerUserSession::ShowKeyboard");
181     auto clientInfo = GetClientInfo(currentClient->AsObject());
182     if (clientInfo == nullptr) {
183         IMSA_HILOGE("client info is nullptr");
184         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
185     }
186     auto data = GetImeData(clientInfo->bindImeType);
187     if (data == nullptr) {
188         IMSA_HILOGE("ime: %{public}d is not exist", clientInfo->bindImeType);
189         return ErrorCode::ERROR_IME_NOT_STARTED;
190     }
191     auto ret = data->core->ShowKeyboard();
192     if (ret != ErrorCode::NO_ERROR) {
193         IMSA_HILOGE("failed to show keyboard, ret: %{public}d", ret);
194         return ErrorCode::ERROR_KBD_SHOW_FAILED;
195     }
196     bool isShowKeyboard = true;
197     UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
198     return ErrorCode::NO_ERROR;
199 }
200 
201 /** Handle the situation a remote input client died.
202  * It's called when a remote input client died
203  * @param the remote object handler of the input client died.
204  */
OnClientDied(sptr<IInputClient> remote)205 void PerUserSession::OnClientDied(sptr<IInputClient> remote)
206 {
207     if (remote == nullptr) {
208         return;
209     }
210     IMSA_HILOGI("userId: %{public}d", userId_);
211     if (IsSameClient(remote, GetCurrentClient())) {
212         auto clientInfo = GetClientInfo(remote->AsObject());
213         StopImeInput(clientInfo->bindImeType, clientInfo->channel);
214         SetCurrentClient(nullptr);
215         ExitCurrentInputType();
216     }
217     RemoveClientInfo(remote->AsObject(), true);
218 }
219 
220 /** Handle the situation that an ime died
221  * It's called when an ime died
222  * @param the remote object handler of the ime who died.
223  */
OnImeDied(const sptr<IInputMethodCore> & remote,ImeType type)224 void PerUserSession::OnImeDied(const sptr<IInputMethodCore> &remote, ImeType type)
225 {
226     if (remote == nullptr) {
227         return;
228     }
229     IMSA_HILOGI("type: %{public}d", type);
230     RemoveImeData(type, true);
231     InputTypeManager::GetInstance().Set(false);
232     auto client = GetCurrentClient();
233     auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
234     if (clientInfo != nullptr && clientInfo->bindImeType == type) {
235         StopClientInput(client);
236         if (type == ImeType::IME) {
237             RestartIme();
238         }
239     }
240 }
241 
RemoveIme(const sptr<IInputMethodCore> & core,ImeType type)242 int32_t PerUserSession::RemoveIme(const sptr<IInputMethodCore> &core, ImeType type)
243 {
244     if (core == nullptr) {
245         return ErrorCode::ERROR_NULL_POINTER;
246     }
247     auto data = GetImeData(type);
248     if (data == nullptr || data->core->AsObject() != core->AsObject()) {
249         return ErrorCode::ERROR_IME_NOT_STARTED;
250     }
251 
252     auto client = GetCurrentClient();
253     auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
254     if (clientInfo != nullptr && clientInfo->bindImeType == type) {
255         UnBindClientWithIme(clientInfo);
256     }
257     RemoveImeData(type, true);
258     return ErrorCode::NO_ERROR;
259 }
260 
UpdateCurrentUserId(int32_t userId)261 void PerUserSession::UpdateCurrentUserId(int32_t userId)
262 {
263     userId_ = userId;
264 }
265 
OnHideCurrentInput()266 int32_t PerUserSession::OnHideCurrentInput()
267 {
268     sptr<IInputClient> client = GetCurrentClient();
269     if (client == nullptr) {
270         IMSA_HILOGE("current client is nullptr");
271         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
272     }
273     return HideKeyboard(client);
274 }
275 
OnShowCurrentInput()276 int32_t PerUserSession::OnShowCurrentInput()
277 {
278     IMSA_HILOGD("PerUserSession::OnShowCurrentInput");
279     sptr<IInputClient> client = GetCurrentClient();
280     if (client == nullptr) {
281         IMSA_HILOGE("current client is nullptr");
282         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
283     }
284     return ShowKeyboard(client);
285 }
286 
OnHideInput(sptr<IInputClient> client)287 int32_t PerUserSession::OnHideInput(sptr<IInputClient> client)
288 {
289     IMSA_HILOGD("PerUserSession::OnHideInput");
290     if (!IsSameClient(client, GetCurrentClient())) {
291         IMSA_HILOGE("client is not current client");
292         return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
293     }
294     return HideKeyboard(client);
295 }
296 
OnShowInput(sptr<IInputClient> client)297 int32_t PerUserSession::OnShowInput(sptr<IInputClient> client)
298 {
299     IMSA_HILOGD("PerUserSession::OnShowInput");
300     if (!IsSameClient(client, GetCurrentClient())) {
301         IMSA_HILOGE("client is not current client");
302         return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
303     }
304     return ShowKeyboard(client);
305 }
306 
OnHideSoftKeyBoardSelf()307 void PerUserSession::OnHideSoftKeyBoardSelf()
308 {
309     IMSA_HILOGD("run in");
310     sptr<IInputClient> client = GetCurrentClient();
311     if (client == nullptr) {
312         IMSA_HILOGE("current client is nullptr");
313         return;
314     }
315     UpdateClientInfo(client->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
316     ExitCurrentInputType();
317 }
318 
OnRequestShowInput()319 int32_t PerUserSession::OnRequestShowInput()
320 {
321     IMSA_HILOGD("run in");
322     auto data = GetImeData(ImeType::IME);
323     if (data == nullptr) {
324         IMSA_HILOGE("ime: %{public}d doesn't exist", ImeType::IME);
325         return ErrorCode::ERROR_IME_NOT_STARTED;
326     }
327     auto ret = data->core->ShowKeyboard();
328     if (ret != ErrorCode::NO_ERROR) {
329         IMSA_HILOGE("failed to show keyboard, ret: %{public}d", ret);
330         return ErrorCode::ERROR_KBD_SHOW_FAILED;
331     }
332     auto currentClient = GetCurrentClient();
333     if (currentClient != nullptr) {
334         UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, true } });
335     }
336     return ErrorCode::NO_ERROR;
337 }
338 
OnRequestHideInput()339 int32_t PerUserSession::OnRequestHideInput()
340 {
341     IMSA_HILOGD("run in");
342     auto data = GetImeData(ImeType::IME);
343     if (data == nullptr) {
344         IMSA_HILOGE("ime: %{public}d doesn't exist", ImeType::IME);
345         return ErrorCode::ERROR_IME_NOT_STARTED;
346     }
347     auto ret = data->core->HideKeyboard();
348     if (ret != ErrorCode::NO_ERROR) {
349         IMSA_HILOGE("failed to hide keyboard, ret: %{public}d", ret);
350         return ErrorCode::ERROR_KBD_HIDE_FAILED;
351     }
352     auto currentClient = GetCurrentClient();
353     if (currentClient != nullptr) {
354         UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
355     }
356     ExitCurrentInputType();
357     return ErrorCode::NO_ERROR;
358 }
359 
360 /** Get ClientInfo
361  * @param inputClient the IRemoteObject remote handler of given input client
362  * @return a pointer of ClientInfo if client is found
363  *         null if client is not found
364  * @note the clientInfo pointer should not be freed by caller
365  */
GetClientInfo(sptr<IRemoteObject> inputClient)366 std::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(sptr<IRemoteObject> inputClient)
367 {
368     if (inputClient == nullptr) {
369         IMSA_HILOGE("inputClient is nullptr");
370         return nullptr;
371     }
372     std::lock_guard<std::recursive_mutex> lock(mtx);
373     auto it = mapClients_.find(inputClient);
374     if (it == mapClients_.end()) {
375         IMSA_HILOGD("client not found");
376         return nullptr;
377     }
378     return it->second;
379 }
380 
GetClientInfo(pid_t pid)381 std::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(pid_t pid)
382 {
383     std::lock_guard<std::recursive_mutex> lock(mtx);
384     auto iter = std::find_if(
385         mapClients_.begin(), mapClients_.end(), [pid](const auto &mapClient) { return mapClient.second->pid == pid; });
386     if (iter == mapClients_.end()) {
387         IMSA_HILOGD("not found");
388         return nullptr;
389     }
390     return iter->second;
391 }
392 
OnPrepareInput(const InputClientInfo & clientInfo)393 int32_t PerUserSession::OnPrepareInput(const InputClientInfo &clientInfo)
394 {
395     IMSA_HILOGD("PerUserSession::OnPrepareInput Start");
396     return AddClientInfo(clientInfo.client->AsObject(), clientInfo, PREPARE_INPUT);
397 }
398 
399 /** Release input. Called by an input client.Run in work thread of this user
400  * @param the parameters from remote client
401  * @return ErrorCode
402  */
OnReleaseInput(const sptr<IInputClient> & client)403 int32_t PerUserSession::OnReleaseInput(const sptr<IInputClient> &client)
404 {
405     IMSA_HILOGD("PerUserSession::Start");
406     return RemoveClient(client, true);
407 }
408 
RemoveClient(const sptr<IInputClient> & client,bool isUnbindFromClient)409 int32_t PerUserSession::RemoveClient(const sptr<IInputClient> &client, bool isUnbindFromClient)
410 {
411     if (client == nullptr) {
412         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
413     }
414     // if client is current client, unbind firstly
415     if (IsSameClient(client, GetCurrentClient())) {
416         UnBindClientWithIme(GetClientInfo(client->AsObject()), isUnbindFromClient);
417         SetCurrentClient(nullptr);
418         ExitCurrentInputType();
419     }
420     if (IsSameClient(client, GetInactiveClient())) {
421         SetInactiveClient(nullptr);
422     }
423     StopClientInput(client);
424     RemoveClientInfo(client->AsObject());
425     return ErrorCode::NO_ERROR;
426 }
427 
DeactivateClient(const sptr<IInputClient> & client)428 void PerUserSession::DeactivateClient(const sptr<IInputClient> &client)
429 {
430     if (client == nullptr) {
431         IMSA_HILOGD("client is nullptr");
432         return;
433     }
434     auto clientInfo = GetClientInfo(client->AsObject());
435     if (clientInfo == nullptr) {
436         return;
437     }
438     IMSA_HILOGI("deactivate client[%{public}d]", clientInfo->pid);
439     UpdateClientInfo(client->AsObject(), { { UpdateFlag::STATE, ClientState::INACTIVE } });
440     if (IsSameClient(client, GetCurrentClient())) {
441         SetCurrentClient(nullptr);
442     }
443     SetInactiveClient(client);
444     client->DeactivateClient();
445     if (InputTypeManager::GetInstance().IsStarted()) {
446         ExitCurrentInputType();
447         return;
448     }
449     auto data = GetImeData(clientInfo->bindImeType);
450     if (data == nullptr) {
451         IMSA_HILOGE("ime %{public}d doesn't exist", clientInfo->bindImeType);
452         return;
453     }
454     data->core->OnClientInactive(clientInfo->channel);
455 }
456 
IsProxyImeEnable()457 bool PerUserSession::IsProxyImeEnable()
458 {
459     auto data = GetImeData(ImeType::PROXY_IME);
460     return data != nullptr && data->core != nullptr && data->core->IsEnable();
461 }
462 
OnStartInput(const InputClientInfo & inputClientInfo,sptr<IRemoteObject> & agent)463 int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
464 {
465     const sptr<IInputClient> &client = inputClientInfo.client;
466     if (client == nullptr) {
467         IMSA_HILOGE("client is nullptr");
468         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
469     }
470     auto clientInfo = GetClientInfo(client->AsObject());
471     if (clientInfo == nullptr) {
472         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
473     }
474     IMSA_HILOGD("start input with keyboard[%{public}d]", inputClientInfo.isShowKeyboard);
475     if (IsSameClient(client, GetCurrentClient()) && IsImeBindChanged(clientInfo->bindImeType)) {
476         UnBindClientWithIme(clientInfo);
477     }
478     InputClientInfo infoTemp = *clientInfo;
479     infoTemp.isShowKeyboard = inputClientInfo.isShowKeyboard;
480     infoTemp.isNotifyInputStart = inputClientInfo.isNotifyInputStart;
481     auto imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME;
482     int32_t ret = BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), imeType, true);
483     if (ret != ErrorCode::NO_ERROR) {
484         IMSA_HILOGE("bind failed, ret: %{public}d", ret);
485         return ret;
486     }
487     auto data = GetImeData(imeType);
488     if (data == nullptr || data->agent == nullptr) {
489         IMSA_HILOGE("data or agent is nullptr.");
490         return ErrorCode::ERROR_IME_NOT_STARTED;
491     }
492     agent = data->agent->AsObject();
493     return ErrorCode::NO_ERROR;
494 }
495 
BindClientWithIme(const std::shared_ptr<InputClientInfo> & clientInfo,ImeType type,bool isBindFromClient)496 int32_t PerUserSession::BindClientWithIme(
497     const std::shared_ptr<InputClientInfo> &clientInfo, ImeType type, bool isBindFromClient)
498 {
499     if (clientInfo == nullptr) {
500         IMSA_HILOGE("clientInfo is nullptr");
501         return ErrorCode::ERROR_NULL_POINTER;
502     }
503     IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d", type,
504         clientInfo->isShowKeyboard, isBindFromClient);
505     auto data = GetValidIme(type);
506     if (data == nullptr) {
507         return ErrorCode::ERROR_IME_NOT_STARTED;
508     }
509     auto ret = data->core->StartInput(*clientInfo, isBindFromClient);
510     if (ret != ErrorCode::NO_ERROR) {
511         IMSA_HILOGE("start input failed, ret: %{public}d", ret);
512         return ErrorCode::ERROR_IME_START_INPUT_FAILED;
513     }
514     if (!isBindFromClient && clientInfo->client->OnInputReady(data->agent) != ErrorCode::NO_ERROR) {
515         IMSA_HILOGE("start client input failed, ret: %{public}d", ret);
516         return ErrorCode::ERROR_EX_PARCELABLE;
517     }
518     UpdateClientInfo(clientInfo->client->AsObject(),
519         { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard },
520             { UpdateFlag::STATE, ClientState::ACTIVE } });
521     ReplaceCurrentClient(clientInfo->client);
522     return ErrorCode::NO_ERROR;
523 }
524 
UnBindClientWithIme(const std::shared_ptr<InputClientInfo> & currentClientInfo,bool isUnbindFromClient)525 void PerUserSession::UnBindClientWithIme(
526     const std::shared_ptr<InputClientInfo> &currentClientInfo, bool isUnbindFromClient)
527 {
528     if (currentClientInfo == nullptr) {
529         return;
530     }
531     if (!isUnbindFromClient) {
532         IMSA_HILOGD("Unbind from service.");
533         StopClientInput(currentClientInfo->client);
534     }
535     StopImeInput(currentClientInfo->bindImeType, currentClientInfo->channel);
536 }
537 
StopClientInput(const sptr<IInputClient> & currentClient)538 void PerUserSession::StopClientInput(const sptr<IInputClient> &currentClient)
539 {
540     if (currentClient == nullptr) {
541         return;
542     }
543     auto ret = currentClient->OnInputStop();
544     IMSA_HILOGI("stop client input, ret: %{public}d", ret);
545 }
546 
StopImeInput(ImeType currentType,const sptr<IInputDataChannel> & currentChannel)547 void PerUserSession::StopImeInput(ImeType currentType, const sptr<IInputDataChannel> &currentChannel)
548 {
549     auto data = GetImeData(currentType);
550     if (data == nullptr) {
551         return;
552     }
553     auto ret = data->core->StopInput(currentChannel);
554     IMSA_HILOGI("stop ime input, ret: %{public}d", ret);
555 }
556 
OnSecurityChange(int32_t & security)557 void PerUserSession::OnSecurityChange(int32_t &security)
558 {
559     auto data = GetImeData(ImeType::IME);
560     if (data == nullptr) {
561         IMSA_HILOGE("ime: %{public}d is not exist", ImeType::IME);
562         return;
563     }
564     auto ret = data->core->OnSecurityChange(security);
565     IMSA_HILOGD("on security change, ret: %{public}d", ret);
566 }
567 
OnSetCoreAndAgent(const sptr<IInputMethodCore> & core,const sptr<IInputMethodAgent> & agent)568 int32_t PerUserSession::OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IInputMethodAgent> &agent)
569 {
570     IMSA_HILOGI("run in");
571     auto imeType = ImeType::IME;
572     auto ret = AddImeData(imeType, core, agent);
573     if (ret != ErrorCode::NO_ERROR) {
574         return ret;
575     }
576     ret = InitInputControlChannel();
577     IMSA_HILOGI("init input control channel ret: %{public}d", ret);
578 
579     auto client = GetCurrentClient();
580     auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
581     if (clientInfo != nullptr && IsImeStartInBind(clientInfo->bindImeType, imeType)) {
582         BindClientWithIme(clientInfo, imeType);
583     }
584     bool isStarted = true;
585     isImeStarted_.SetValue(isStarted);
586     return ErrorCode::NO_ERROR;
587 }
588 
OnRegisterProxyIme(const sptr<IInputMethodCore> & core,const sptr<IInputMethodAgent> & agent)589 int32_t PerUserSession::OnRegisterProxyIme(const sptr<IInputMethodCore> &core, const sptr<IInputMethodAgent> &agent)
590 {
591     IMSA_HILOGD("run in");
592     auto imeType = ImeType::PROXY_IME;
593     auto ret = AddImeData(imeType, core, agent);
594     if (ret != ErrorCode::NO_ERROR) {
595         return ret;
596     }
597     auto client = GetCurrentClient();
598     auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
599     if (clientInfo != nullptr) {
600         if (IsProxyImeStartInBind(clientInfo->bindImeType, imeType)) {
601             BindClientWithIme(clientInfo, imeType);
602         }
603         if (IsProxyImeStartInImeBind(clientInfo->bindImeType, imeType)) {
604             UnBindClientWithIme(clientInfo);
605             BindClientWithIme(clientInfo, imeType);
606         }
607     }
608     return ErrorCode::NO_ERROR;
609 }
610 
OnUnRegisteredProxyIme(UnRegisteredType type,const sptr<IInputMethodCore> & core)611 int32_t PerUserSession::OnUnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
612 {
613     IMSA_HILOGD("proxy unregister type: %{public}d", type);
614     // 0: stop proxy  1: switch to ima
615     if (type == UnRegisteredType::REMOVE_PROXY_IME) {
616         RemoveIme(core, ImeType::PROXY_IME);
617         return ErrorCode::NO_ERROR;
618     }
619     if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) {
620         auto client = GetCurrentClient();
621         auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
622         if (clientInfo == nullptr) {
623             IMSA_HILOGE("not find current client");
624             return ErrorCode::ERROR_CLIENT_NOT_BOUND;
625         }
626         if (clientInfo->bindImeType == ImeType::PROXY_IME) {
627             UnBindClientWithIme(clientInfo);
628         }
629         InputClientInfo infoTemp = {
630             .isShowKeyboard = true, .client = clientInfo->client, .channel = clientInfo->channel
631         };
632         return BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), ImeType::IME);
633     }
634     return ErrorCode::ERROR_BAD_PARAMETERS;
635 }
636 
InitInputControlChannel()637 int32_t PerUserSession::InitInputControlChannel()
638 {
639     IMSA_HILOGD("PerUserSession::InitInputControlChannel");
640     sptr<IInputControlChannel> inputControlChannel = new InputControlChannelStub(userId_);
641     auto data = GetImeData(ImeType::IME);
642     if (data == nullptr) {
643         IMSA_HILOGE("ime: %{public}d is not exist", ImeType::IME);
644         return ErrorCode::ERROR_IME_NOT_STARTED;
645     }
646     return data->core->InitInputControlChannel(inputControlChannel);
647 }
648 
IsRestartIme()649 bool PerUserSession::IsRestartIme()
650 {
651     IMSA_HILOGD("PerUserSession::IsRestartIme");
652     std::lock_guard<std::mutex> lock(resetLock);
653     auto now = time(nullptr);
654     if (difftime(now, manager.last) > IME_RESET_TIME_OUT) {
655         manager = { 0, now };
656     }
657     ++manager.num;
658     return manager.num <= MAX_RESTART_NUM;
659 }
660 
RestartIme()661 void PerUserSession::RestartIme()
662 {
663     IMSA_HILOGI("user: %{public}d ime restart", userId_);
664     if (!IsRestartIme()) {
665         IMSA_HILOGI("ime deaths over max num");
666         return;
667     }
668     if (!IsWmsReady()) {
669         IMSA_HILOGI("wms not ready, wait");
670         return;
671     }
672     StartCurrentIme(userId_, true);
673 }
674 
SetCurrentClient(sptr<IInputClient> client)675 void PerUserSession::SetCurrentClient(sptr<IInputClient> client)
676 {
677     IMSA_HILOGD("set current client");
678     std::lock_guard<std::mutex> lock(clientLock_);
679     currentClient_ = client;
680 }
681 
GetCurrentClient()682 sptr<IInputClient> PerUserSession::GetCurrentClient()
683 {
684     IMSA_HILOGD("get current client");
685     std::lock_guard<std::mutex> lock(clientLock_);
686     return currentClient_;
687 }
688 
ReplaceCurrentClient(const sptr<IInputClient> & client)689 void PerUserSession::ReplaceCurrentClient(const sptr<IInputClient> &client)
690 {
691     std::lock_guard<std::mutex> lock(focusedClientLock_);
692     if (client == nullptr) {
693         return;
694     }
695     auto clientInfo = GetClientInfo(client->AsObject());
696     if (clientInfo == nullptr) {
697         return;
698     }
699     auto replacedClient = GetCurrentClient();
700     SetCurrentClient(client);
701     if (replacedClient != nullptr) {
702         auto replacedClientInfo = GetClientInfo(replacedClient->AsObject());
703         if (replacedClientInfo != nullptr && replacedClientInfo->pid != clientInfo->pid) {
704             IMSA_HILOGI("remove replaced client[%{public}d]", replacedClientInfo->pid);
705             RemoveClient(replacedClient);
706         }
707     }
708     auto inactiveClient = GetInactiveClient();
709     if (inactiveClient != nullptr) {
710         auto inactiveClientInfo = GetClientInfo(inactiveClient->AsObject());
711         if (inactiveClientInfo != nullptr && inactiveClientInfo->pid != clientInfo->pid) {
712             IMSA_HILOGI("remove inactive client[%{public}d]", inactiveClientInfo->pid);
713             RemoveClientInfo(inactiveClient->AsObject());
714         }
715     }
716     SetInactiveClient(nullptr);
717 }
718 
SetInactiveClient(sptr<IInputClient> client)719 void PerUserSession::SetInactiveClient(sptr<IInputClient> client)
720 {
721     IMSA_HILOGD("set inactive client");
722     std::lock_guard<std::mutex> lock(inactiveClientLock_);
723     inactiveClient_ = client;
724 }
725 
GetInactiveClient()726 sptr<IInputClient> PerUserSession::GetInactiveClient()
727 {
728     std::lock_guard<std::mutex> lock(inactiveClientLock_);
729     return inactiveClient_;
730 }
731 
NotifyImeChangeToClients(const Property & property,const SubProperty & subProperty)732 void PerUserSession::NotifyImeChangeToClients(const Property &property, const SubProperty &subProperty)
733 {
734     IMSA_HILOGD("start");
735     std::lock_guard<std::recursive_mutex> lock(mtx);
736     for (const auto &client : mapClients_) {
737         auto clientInfo = client.second;
738         if (clientInfo == nullptr || !EventStatusManager::IsImeChangeOn(clientInfo->eventFlag)) {
739             IMSA_HILOGD("client nullptr or no need to notify");
740             continue;
741         }
742         IMSA_HILOGD("notify client[%{public}d]", static_cast<int32_t>(clientInfo->pid));
743         int32_t ret = clientInfo->client->OnSwitchInput(property, subProperty);
744         if (ret != ErrorCode::NO_ERROR) {
745             IMSA_HILOGE("notify failed, ret: %{public}d, uid: %{public}d", ret, static_cast<int32_t>(clientInfo->uid));
746             continue;
747         }
748     }
749 }
750 
AddImeData(ImeType type,sptr<IInputMethodCore> core,sptr<IInputMethodAgent> agent)751 int32_t PerUserSession::AddImeData(ImeType type, sptr<IInputMethodCore> core, sptr<IInputMethodAgent> agent)
752 {
753     if (core == nullptr || agent == nullptr) {
754         IMSA_HILOGE("core or agent is nullptr");
755         return ErrorCode::ERROR_NULL_POINTER;
756     }
757     sptr<InputDeathRecipient> deathRecipient = new (std::nothrow) InputDeathRecipient();
758     if (deathRecipient == nullptr) {
759         IMSA_HILOGE("failed to new deathRecipient");
760         return ErrorCode::ERROR_NULL_POINTER;
761     }
762     deathRecipient->SetDeathRecipient([this, core, type](const wptr<IRemoteObject> &) { this->OnImeDied(core, type); });
763     auto coreObject = core->AsObject();
764     if (coreObject == nullptr || !coreObject->AddDeathRecipient(deathRecipient)) {
765         IMSA_HILOGE("failed to add death recipient");
766         return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED;
767     }
768     std::lock_guard<std::mutex> lock(imeDataLock_);
769     imeData_.insert_or_assign(type, std::make_shared<ImeData>(core, agent, deathRecipient));
770     return ErrorCode::NO_ERROR;
771 }
772 
GetImeData(ImeType type)773 std::shared_ptr<ImeData> PerUserSession::GetImeData(ImeType type)
774 {
775     std::lock_guard<std::mutex> lock(imeDataLock_);
776     auto it = imeData_.find(type);
777     if (it == imeData_.end()) {
778         return nullptr;
779     }
780     return it->second;
781 }
782 
GetValidIme(ImeType type)783 std::shared_ptr<ImeData> PerUserSession::GetValidIme(ImeType type)
784 {
785     auto data = GetImeData(type);
786     if (data != nullptr || type != ImeType::IME) {
787         return data;
788     }
789     IMSA_HILOGI("current ime is empty, try to restart it");
790     if (!StartCurrentIme(userId_, true)) {
791         return nullptr;
792     }
793     return GetImeData(type);
794 }
795 
RemoveImeData(ImeType type,bool isImeDied)796 void PerUserSession::RemoveImeData(ImeType type, bool isImeDied)
797 {
798     std::lock_guard<std::mutex> lock(imeDataLock_);
799     auto it = imeData_.find(type);
800     if (it == imeData_.end()) {
801         IMSA_HILOGD("imeData not found");
802         return;
803     }
804     auto data = it->second;
805     if (isImeDied && data->core != nullptr && data->core->AsObject() != nullptr) {
806         data->core->AsObject()->RemoveDeathRecipient(data->deathRecipient);
807         data->deathRecipient = nullptr;
808     }
809     imeData_.erase(type);
810 }
811 
OnFocused(int32_t pid,int32_t uid)812 void PerUserSession::OnFocused(int32_t pid, int32_t uid)
813 {
814     std::lock_guard<std::mutex> lock(focusedClientLock_);
815     auto client = GetCurrentClient();
816     if (client == nullptr) {
817         return;
818     }
819     if (IsCurrentClient(pid, uid)) {
820         IMSA_HILOGD("pid[%{public}d] same as current client", pid);
821         return;
822     }
823     if (!OHOS::Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
824         IMSA_HILOGI("focus shifts to pid: %{public}d, remove current client", pid);
825         RemoveClient(client);
826         InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
827         return;
828     }
829     IMSA_HILOGI("focus shifts to pid: %{public}d, deactivate current client", pid);
830     DeactivateClient(client);
831 }
832 
OnUnfocused(int32_t pid,int32_t uid)833 void PerUserSession::OnUnfocused(int32_t pid, int32_t uid)
834 {
835     if (GetCurrentClient() == nullptr) {
836         return;
837     }
838     if (IsCurrentClient(pid, uid)) {
839         IMSA_HILOGD("pid[%{public}d] same as current client", pid);
840         return;
841     }
842     auto clientInfo = GetClientInfo(pid);
843     if (clientInfo == nullptr) {
844         return;
845     }
846     RemoveClient(clientInfo->client);
847     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
848 }
849 
IsCurrentClient(int32_t pid,int32_t uid)850 bool PerUserSession::IsCurrentClient(int32_t pid, int32_t uid)
851 {
852     auto client = GetCurrentClient();
853     if (client == nullptr) {
854         IMSA_HILOGD("no client in bound state");
855         return false;
856     }
857     auto clientInfo = GetClientInfo(client->AsObject());
858     if (clientInfo == nullptr) {
859         IMSA_HILOGE("failed to get client info");
860         return false;
861     }
862     return clientInfo->pid == pid && clientInfo->uid == uid;
863 }
864 
IsSameClient(sptr<IInputClient> source,sptr<IInputClient> dest)865 bool PerUserSession::IsSameClient(sptr<IInputClient> source, sptr<IInputClient> dest)
866 {
867     return source != nullptr && dest != nullptr && source->AsObject() == dest->AsObject();
868 }
869 
StartCurrentIme(int32_t userId,bool isRetry)870 bool PerUserSession::StartCurrentIme(int32_t userId, bool isRetry)
871 {
872     auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
873     auto imeToStart = ImeInfoInquirer::GetInstance().GetImeToStart(userId);
874     IMSA_HILOGD("currentIme: %{public}s, imeToStart: %{public}s", currentIme->imeId.c_str(), imeToStart->imeId.c_str());
875     if (!StartInputService(imeToStart, isRetry)) {
876         IMSA_HILOGE("failed to start ime");
877         InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
878             ErrorCode::ERROR_IME_START_FAILED, imeToStart->imeId, "start ime failed!");
879         return false;
880     }
881     if (currentIme->imeId == imeToStart->imeId) {
882         return true;
883     }
884     IMSA_HILOGI("current ime changed to %{public}s", imeToStart->imeId.c_str());
885     auto currentImeInfo = ImeInfoInquirer::GetInstance().GetCurrentImeInfo();
886     if (currentImeInfo != nullptr) {
887         NotifyImeChangeToClients(currentImeInfo->prop, currentImeInfo->subProp);
888     }
889     return true;
890 }
891 
StopCurrentIme()892 void PerUserSession::StopCurrentIme()
893 {
894     auto data = GetImeData(ImeType::IME);
895     if (data == nullptr) {
896         IMSA_HILOGE("ime doesn't exist");
897         return;
898     }
899     IMSA_HILOGI("start");
900     RemoveImeData(ImeType::IME, true);
901     auto client = GetCurrentClient();
902     auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
903     if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
904         StopClientInput(client);
905     }
906     data->core->StopInputService(true);
907 }
908 
ActivateIme(const std::shared_ptr<ImeNativeCfg> & ime,bool isRetry)909 bool PerUserSession::ActivateIme(const std::shared_ptr<ImeNativeCfg> &ime, bool isRetry)
910 {
911     if (ime == nullptr) {
912         IMSA_HILOGE("target ime is nullptr");
913         return false;
914     }
915     auto cacheData = ImeAgingManager::GetInstance().Pop(ime->bundleName);
916     if (cacheData == nullptr) {
917         IMSA_HILOGD("miss the ime cache");
918         return StartInputService(ime, isRetry);
919     }
920     IMSA_HILOGI("start the cached ime");
921     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, ime->bundleName, ime->subName);
922     if (info == nullptr) {
923         IMSA_HILOGE("failed to get ime info");
924         return false;
925     }
926     if (!info->isNewIme && StartInputService(ime, false)) {
927         IMSA_HILOGD("old ime, need to start ability");
928         return true;
929     }
930     if (cacheData->core != nullptr) {
931         IMSA_HILOGD("inform subtype: %{public}s", ime->subName.c_str());
932         cacheData->core->SetSubtype(info->subProp);
933     }
934     return OnSetCoreAndAgent(cacheData->core, cacheData->agent) == ErrorCode::NO_ERROR;
935 }
936 
DeactivateIme(const std::string & bundleName,const std::string & subName)937 void PerUserSession::DeactivateIme(const std::string &bundleName, const std::string &subName)
938 {
939     auto data = GetImeData(ImeType::IME);
940     if (data == nullptr) {
941         IMSA_HILOGE("ime: %{public}d is not exist", ImeType::IME);
942         return;
943     }
944     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
945     if ((info == nullptr || !info->isNewIme) && data->core != nullptr) {
946         IMSA_HILOGI("stop ime: %{public}s/%{public}s", bundleName.c_str(), subName.c_str());
947         data->core->StopInputService(true);
948         RemoveImeData(ImeType::IME, true);
949         return;
950     }
951 
952     IMSA_HILOGI("deactivate ime: %{public}s/%{public}s", bundleName.c_str(), subName.c_str());
953     if (data->deathRecipient != nullptr) {
954         data->deathRecipient->SetDeathRecipient(
955             [this, bundleName](const wptr<IRemoteObject> &) { ImeAgingManager::GetInstance().Pop(bundleName); });
956     }
957     ImeAgingManager::GetInstance().Push(bundleName, data);
958     auto client = GetCurrentClient();
959     auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
960     if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
961         UnBindClientWithIme(clientInfo, false);
962     }
963     RemoveImeData(ImeType::IME, false);
964 }
965 
StartInputService(const std::shared_ptr<ImeNativeCfg> & ime,bool isRetry)966 bool PerUserSession::StartInputService(const std::shared_ptr<ImeNativeCfg> &ime, bool isRetry)
967 {
968     IMSA_HILOGI("start %{public}s with isRetry: %{public}d", ime->imeId.c_str(), isRetry);
969     AAFwk::Want want;
970     want.SetElementName(ime->bundleName, ime->extName);
971     isImeStarted_.Clear(false);
972     auto ret = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(
973         want, nullptr, userId_, AppExecFwk::ExtensionAbilityType::INPUTMETHOD);
974     if (ret != ErrorCode::NO_ERROR) {
975         IMSA_HILOGE("failed to start ability");
976         InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
977             ErrorCode::ERROR_IME_START_FAILED, ime->imeId, "StartInputService, failed to start ability.");
978     } else if (isImeStarted_.GetValue()) {
979         IMSA_HILOGI("ime started successfully");
980         InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::START_IME);
981         return true;
982     }
983     if (isRetry) {
984         IMSA_HILOGE("failed to start ime, begin to retry five times");
985         auto retryTask = [this, ime]() {
986             pthread_setname_np(pthread_self(), "ImeRestart");
987             BlockRetry(
988                 IME_RESTART_INTERVAL, IME_RESTART_TIMES, [this, ime]() { return StartInputService(ime, false); });
989         };
990         std::thread(retryTask).detach();
991     }
992     return false;
993 }
994 
GetCurrentClientPid()995 int64_t PerUserSession::GetCurrentClientPid()
996 {
997     auto client = GetCurrentClient();
998     if (client == nullptr) {
999         return INVALID_PID;
1000     }
1001     auto clientInfo = GetClientInfo(client->AsObject());
1002     if (clientInfo == nullptr) {
1003         return INVALID_PID;
1004     }
1005     return clientInfo->pid;
1006 }
1007 
OnPanelStatusChange(const InputWindowStatus & status,const InputWindowInfo & windowInfo)1008 int32_t PerUserSession::OnPanelStatusChange(const InputWindowStatus &status, const InputWindowInfo &windowInfo)
1009 {
1010     auto clientMap = GetClientMap();
1011     for (const auto &client : clientMap) {
1012         auto clientInfo = client.second;
1013         if (clientInfo == nullptr) {
1014             IMSA_HILOGD("client nullptr or no need to notify");
1015             continue;
1016         }
1017         if (status == InputWindowStatus::SHOW && !EventStatusManager::IsImeShowOn(clientInfo->eventFlag)) {
1018             IMSA_HILOGD("has no imeShow callback");
1019             continue;
1020         }
1021         if (status == InputWindowStatus::HIDE && !EventStatusManager::IsImeHideOn(clientInfo->eventFlag)) {
1022             IMSA_HILOGD("has no imeHide callback");
1023             continue;
1024         }
1025         int32_t ret = clientInfo->client->OnPanelStatusChange(status, { windowInfo });
1026         if (ret != ErrorCode::NO_ERROR) {
1027             IMSA_HILOGE("OnPanelStatusChange failed, ret: %{public}d", ret);
1028             continue;
1029         }
1030     }
1031     return ErrorCode::NO_ERROR;
1032 }
1033 
OnUpdateListenEventFlag(const InputClientInfo & clientInfo)1034 int32_t PerUserSession::OnUpdateListenEventFlag(const InputClientInfo &clientInfo)
1035 {
1036     auto remoteClient = clientInfo.client->AsObject();
1037     auto ret = AddClientInfo(remoteClient, clientInfo, START_LISTENING);
1038     if (ret != ErrorCode::NO_ERROR) {
1039         IMSA_HILOGE("AddClientInfo failed");
1040         return ret;
1041     }
1042     auto info = GetClientInfo(remoteClient);
1043     if (info == nullptr) {
1044         IMSA_HILOGE("info is nullptr");
1045         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
1046     }
1047     if (info->eventFlag == EventStatusManager::NO_EVENT_ON && info->bindImeType == ImeType::NONE) {
1048         RemoveClientInfo(remoteClient, false);
1049     }
1050     return ErrorCode::NO_ERROR;
1051 }
1052 
IsWmsReady()1053 bool PerUserSession::IsWmsReady()
1054 {
1055     if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
1056         IMSA_HILOGI("scb enable");
1057         return WmsConnectionObserver::IsWmsConnected(userId_);
1058     }
1059     sptr<ISystemAbilityManager> systemAbilityManager =
1060         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1061     if (systemAbilityManager == nullptr) {
1062         IMSA_HILOGI("system ability manager is nullptr");
1063         return false;
1064     }
1065     auto systemAbility = systemAbilityManager->GetSystemAbility(WINDOW_MANAGER_SERVICE_ID, "");
1066     if (systemAbility == nullptr) {
1067         IMSA_HILOGI("window manager service not found");
1068         return false;
1069     }
1070     return true;
1071 }
1072 
IsImeStartInBind(ImeType bindImeType,ImeType startImeType)1073 bool PerUserSession::IsImeStartInBind(ImeType bindImeType, ImeType startImeType)
1074 {
1075     return startImeType == ImeType::IME && bindImeType == ImeType::IME;
1076 }
1077 
IsProxyImeStartInBind(ImeType bindImeType,ImeType startImeType)1078 bool PerUserSession::IsProxyImeStartInBind(ImeType bindImeType, ImeType startImeType)
1079 {
1080     return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::PROXY_IME;
1081 }
1082 
IsProxyImeStartInImeBind(ImeType bindImeType,ImeType startImeType)1083 bool PerUserSession::IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType)
1084 {
1085     return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::IME;
1086 }
1087 
IsBindProxyImeInImeBind(ImeType bindImeType)1088 bool PerUserSession::IsBindProxyImeInImeBind(ImeType bindImeType)
1089 {
1090     return bindImeType == ImeType::IME && IsProxyImeEnable();
1091 }
1092 
IsBindImeInProxyImeBind(ImeType bindImeType)1093 bool PerUserSession::IsBindImeInProxyImeBind(ImeType bindImeType)
1094 {
1095     return bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable();
1096 }
1097 
IsImeBindChanged(ImeType bindImeType)1098 bool PerUserSession::IsImeBindChanged(ImeType bindImeType)
1099 {
1100     return (bindImeType == ImeType::IME && IsProxyImeEnable())
1101            || (bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable());
1102 }
1103 
SwitchSubtype(const SubProperty & subProperty)1104 int32_t PerUserSession::SwitchSubtype(const SubProperty &subProperty)
1105 {
1106     auto data = GetValidIme(ImeType::IME);
1107     if (data == nullptr) {
1108         IMSA_HILOGE("ime: %{public}d is not exist", ImeType::IME);
1109         return ErrorCode::ERROR_IME_NOT_STARTED;
1110     }
1111     return data->core->SetSubtype(subProperty);
1112 }
1113 
IsBoundToClient()1114 bool PerUserSession::IsBoundToClient()
1115 {
1116     if (GetCurrentClient() == nullptr) {
1117         IMSA_HILOGE("not in bound state");
1118         return false;
1119     }
1120     return true;
1121 }
1122 
ExitCurrentInputType()1123 int32_t PerUserSession::ExitCurrentInputType()
1124 {
1125     if (!InputTypeManager::GetInstance().IsStarted()) {
1126         IMSA_HILOGD("already exit");
1127         return ErrorCode::NO_ERROR;
1128     }
1129     auto typeIme = InputTypeManager::GetInstance().GetCurrentIme();
1130     auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1131     if (cfgIme->bundleName == typeIme.bundleName) {
1132         IMSA_HILOGI("only need to switch subtype: %{public}s", cfgIme->subName.c_str());
1133         int32_t ret = SwitchSubtype({ .name = cfgIme->bundleName, .id = cfgIme->subName });
1134         if (ret == ErrorCode::NO_ERROR) {
1135             InputTypeManager::GetInstance().Set(false);
1136         }
1137         return ret;
1138     }
1139     IMSA_HILOGI("need switch ime to: %{public}s", cfgIme->imeId.c_str());
1140     StopCurrentIme();
1141     InputTypeManager::GetInstance().Set(false);
1142     if (!StartInputService(cfgIme, true)) {
1143         IMSA_HILOGE("failed to start ime");
1144         return ErrorCode::ERROR_IME_START_FAILED;
1145     }
1146     return ErrorCode::NO_ERROR;
1147 }
1148 
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1149 int32_t PerUserSession::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1150 {
1151     auto ime = GetImeData(ImeType::IME);
1152     if (ime == nullptr) {
1153         IMSA_HILOGE("ime not started");
1154         return ErrorCode::ERROR_IME_NOT_STARTED;
1155     }
1156     return ime->core->IsPanelShown(panelInfo, isShown);
1157 }
1158 
CheckSecurityMode()1159 bool PerUserSession::CheckSecurityMode()
1160 {
1161     auto client = GetCurrentClient();
1162     auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
1163     if (clientInfo != nullptr) {
1164         return clientInfo->config.inputAttribute.GetSecurityFlag();
1165     }
1166     return false;
1167 }
1168 
GetClientMap()1169 std::map<sptr<IRemoteObject>, std::shared_ptr<InputClientInfo>> PerUserSession::GetClientMap()
1170 {
1171     std::lock_guard<std::recursive_mutex> lock(mtx);
1172     return mapClients_;
1173 }
1174 } // namespace MiscServices
1175 } // namespace OHOS
1176