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