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