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