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> ¤tClient)
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> ¤tClient)
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> ¤tClientInfo, 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> ¤tClient)
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> ¤tChannel)
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