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 43namespace OHOS { 44namespace MiscServices { 45using namespace std::chrono; 46using namespace MessageID; 47using namespace OHOS::AppExecFwk; 48constexpr int64_t INVALID_PID = -1; 49constexpr uint32_t STOP_IME_TIME = 600; 50constexpr const char *STRICT_MODE = "strictMode"; 51constexpr const char *ISOLATED_SANDBOX = "isolatedSandbox"; 52constexpr uint32_t CHECK_IME_RUNNING_RETRY_INTERVAL = 60; 53constexpr uint32_t CHECK_IME_RUNNING_RETRY_TIMES = 10; 54PerUserSession::PerUserSession(int userId) : userId_(userId) 55{ 56} 57 58PerUserSession::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 67PerUserSession::~PerUserSession() 68{ 69} 70 71int 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 113void 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 138void 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 182int32_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 206int32_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 */ 233void 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 */ 261void 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 307int32_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 326int32_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 336int32_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 347int32_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 357int32_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 367void 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 379int32_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 402int32_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 */ 440std::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 455std::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 467int32_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 */ 477int32_t PerUserSession::OnReleaseInput(const sptr<IInputClient> &client) 478{ 479 IMSA_HILOGD("PerUserSession::OnReleaseInput start"); 480 return RemoveClient(client, true); 481} 482 483int32_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 504void 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 539bool PerUserSession::IsProxyImeEnable() 540{ 541 auto data = GetReadyImeData(ImeType::PROXY_IME); 542 return data != nullptr && data->core != nullptr && data->core->IsEnable(); 543} 544 545int32_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 579int32_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 614void 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 627void 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 637void 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 656void 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 668int32_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 695int32_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 717int32_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 743int32_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 756void 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 777void 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 784sptr<IInputClient> PerUserSession::GetCurrentClient() 785{ 786 IMSA_HILOGD("get current client."); 787 std::lock_guard<std::mutex> lock(clientLock_); 788 return currentClient_; 789} 790 791void 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 820void 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 827sptr<IInputClient> PerUserSession::GetInactiveClient() 828{ 829 std::lock_guard<std::mutex> lock(inactiveClientLock_); 830 return inactiveClient_; 831} 832 833void 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 852int32_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 876std::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 889std::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 900void 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 915void 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 936void 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 953std::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 963bool 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 979bool 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 995bool PerUserSession::IsSameClient(sptr<IInputClient> source, sptr<IInputClient> dest) 996{ 997 return source != nullptr && dest != nullptr && source->AsObject() == dest->AsObject(); 998} 999 1000bool 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 1022bool 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 1040AAFwk::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 1061bool 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 1090int64_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 1103int64_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 1116int32_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 1142int32_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 1161bool PerUserSession::IsImeStartInBind(ImeType bindImeType, ImeType startImeType) 1162{ 1163 return startImeType == ImeType::IME && bindImeType == ImeType::IME; 1164} 1165 1166bool PerUserSession::IsProxyImeStartInBind(ImeType bindImeType, ImeType startImeType) 1167{ 1168 return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::PROXY_IME; 1169} 1170 1171bool PerUserSession::IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType) 1172{ 1173 return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::IME; 1174} 1175 1176bool PerUserSession::IsImeBindChanged(ImeType bindImeType) 1177{ 1178 return (bindImeType == ImeType::IME && IsProxyImeEnable()) || 1179 (bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable()); 1180} 1181 1182int32_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 1192int32_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 1203bool PerUserSession::IsBoundToClient() 1204{ 1205 if (GetCurrentClient() == nullptr) { 1206 IMSA_HILOGE("not in bound state!"); 1207 return false; 1208 } 1209 return true; 1210} 1211 1212int32_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 1238bool 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 1249int32_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 1265bool 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 1275std::map<sptr<IRemoteObject>, std::shared_ptr<InputClientInfo>> PerUserSession::GetClientMap() 1276{ 1277 std::lock_guard<std::recursive_mutex> lock(mtx); 1278 return mapClients_; 1279} 1280 1281int32_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 1297int32_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 1314bool 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 1322void 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 1330int32_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 1340bool 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 1349bool 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 1363void 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 1380bool 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 1406BlockQueue<SwitchInfo>& PerUserSession::GetSwitchQueue() 1407{ 1408 return switchQueue_; 1409} 1410 1411int32_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 1425int32_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 1456int32_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 1467std::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 1477bool 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 1496ImeAction 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 1512bool 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 1543bool 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 1560bool PerUserSession::StartNewIme(const std::shared_ptr<ImeNativeCfg> &ime) 1561{ 1562 if (!StopCurrentIme()) { 1563 return false; 1564 } 1565 return StartInputService(ime); 1566} 1567 1568bool 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 1586bool 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 1616bool 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 1630bool 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 1662bool 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 1681int32_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 1703bool 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